CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)

匿名 (未验证) 提交于 2019-12-02 23:57:01

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; } 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!