201709-5
- 这道题有很多种方法来做,最常用的就是线段树和树状数组。
- 如果使用线段树来做,就会想到区间修改的update函数。但是这里可能会涉及到v是1或者a[j]是0的情况,所以用这种方法会超时,最多50分。
- 可以修改一下代码,使用点修改来做这道题。在main函数里面增加一个循环,用来判断。
- 当然,还有一种方法就是树状数组,这种方法和上面这种方法运行时间相差无几,但是代码量大大减少。
- 需要注意的是,如果v是long long型,最好不要用scanf %lld的方式读入,否则超时。
使用线段树代码:
//线段树求解 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<vector> using namespace std; const int maxn=100005; int n,m; int a[maxn]; long long sum[maxn<<2]; void pushup(int id,int l,int r){ int lc=id<<1; int rc=id<<1|1; sum[id]=sum[lc]+sum[rc]; } void build(int id,int l,int r){ if(l==r){ sum[id]=a[l]; return; } int mid=(l+r)>>1; int lc=id<<1; int rc=id<<1|1; build(lc,l,mid); build(rc,mid+1,r); pushup(id,l,r); } //---------------------------区间修改 // void update(int id,int l,int r,int p,int q,int v){ // if(l==r){ // if(sum[id]>=v&&sum[id]%v==0) // sum[id]/=v; // return; // } // int mid=(l+r)>>1; // if(p<=mid){ // update(id<<1,l,mid,p,q,v); // } // if(q>mid){ // update(id<<1|1,mid+1,r,p,q,v); // } // pushup(id,l,r); // } //-------------------------------点修改 void update(int id,int l,int r,int p){ if(l==r){ sum[id]=a[p]; return; } int mid=(l+r)>>1; if(p<=mid){ update(id<<1,l,mid,p); } if(p>mid){ update(id<<1|1,mid+1,r,p); } pushup(id,l,r); } long long query(int id,int l,int r,int p,int q){ long long sums=0; if(p<=l&&q>=r){ return sum[id]; } int mid=(l+r)>>1; if(p<=mid){ sums+=query(id<<1,l,mid,p,q); } if(q>mid){ sums+=query(id<<1|1,mid+1,r,p,q); } return sums; } int main(){ // ios::sync_with_stdio(false); // cin.tie(0); scanf("%d%d",&n,&m); //cin>>n>>m; for(int i=1;i<=n;i++){ //cin>>a[i]; scanf("%d",&a[i]); } build(1,1,n); for(int i=0;i<m;i++){ int opt,p,q; scanf("%d%d%d",&opt,&p,&q); //cin>>opt>>p>>q; if(opt==1){//update int v; scanf("%d",&v); //cout<<v<<endl; //cin>>v; //-------------------------------区间修改 // if(v==1) // continue; // update(1,1,n,p,q,v); if(v==1) continue; // //--------------------------点修改 for(int j=p;j<=q;j++){ if(a[j]>=v&&a[j]%v==0){ a[j]/=v; update(1,1,n,j); } } }else{ cout<<query(1,1,n,p,q)<<endl; } } //system("pause"); return 0; }
使用树状数组代码:
//树状数组求解 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<vector> using namespace std; const int maxn=100005; int n,m; int a[maxn]; long long c[maxn]; int lowbit(int x){ return x&(-x); } long long sum(int x){ long long ret=0; while(x>0){ ret+=c[x]; x-=lowbit(x); } return ret; } void add(int x,int v){ while(x<=n){ c[x]+=v; x+=lowbit(x); } } int main(){ // ios::sync_with_stdio(false); // cin.tie(0); //cin>>n>>m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ //cin>>a[i]; scanf("%d",&a[i]); add(i,a[i]); } for(int i=0;i<m;i++){ int opt; //cin>>opt; scanf("%d",&opt); if(opt==1){ int p,q;int v; //cin>>p>>q>>v; scanf("%d%d%d",&p,&q,&v);//这里不能用%lld来读取long long 型, if(v==1) continue; for(int j=p;j<=q;j++){ if(a[j]>=v&&a[j]%v==0){ add(j,a[j]/v-a[j]); a[j]/=v; } } }else{ int p,q; //cin>>p>>q; scanf("%d%d",&p,&q); cout<<sum(q)-sum(p-1)<<endl; } } //system("pause"); return 0; }
来源:博客园
作者:Garrett_Wale
链接:https://www.cnblogs.com/GarrettWale/p/11456868.html