【模板】CDQ分治
这里贴的代码写的是点修改、区间查询的题。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define LL long long 5 #define rg register 6 #define N 2000010 7 #define mid ((l+r)>>1) 8 using namespace std; 9 int n,m,cnt,tot,ans[N]; 10 struct rec{ 11 int pos,val,type; 12 //对于修改操作,val表示增量,对于查询操作,val表示它是第几个询问; 13 //type为0表示修改,1表示区间左端点(开),2表示区间右端点 14 bool operator<(const rec&x)const{return pos==x.pos?type<x.type:pos<x.pos;} 15 }a[N],tmp[N]; 16 inline int read(){ 17 int k=0,f=1; char c=getchar(); 18 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 19 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 20 return k*f; 21 } 22 void cdq(int l,int r){ 23 if(l>=r) return; 24 cdq(l,mid),cdq(mid+1,r); 25 LL sum=0; int p1=l,p2=mid+1,cnt=0; 26 while(p1<=mid&&p2<=r){ 27 if(a[p1]<a[p2]){ 28 if(!a[p1].type) sum+=a[p1].val; tmp[++cnt]=a[p1++]; 29 } 30 else{ 31 if(a[p2].type==1) ans[a[p2].val]-=sum; 32 else if(a[p2].type==2) ans[a[p2].val]+=sum; 33 tmp[++cnt]=a[p2++]; 34 } 35 } 36 for(rg int i=p1;i<=mid;i++) tmp[++cnt]=a[i]; 37 for(rg int i=p2;i<=r;i++){ 38 if(a[i].type==1) ans[a[i].val]-=sum; 39 else if(a[i].type==2) ans[a[i].val]+=sum; 40 tmp[++cnt]=a[i]; 41 } 42 for(rg int i=l;i<=r;i++) a[i]=tmp[i-l+1]; 43 } 44 int main(){ 45 n=read(); m=read(); 46 for(rg int i=1;i<=n;i++) a[++tot]=(rec){i,read(),0}; 47 for(rg int i=1;i<=m;i++){ 48 int opt=read(),x=read(),y=read(); 49 if(opt==1) a[++tot]=(rec){x,y,0}; 50 else a[++tot]=(rec){x-1,++cnt,1},a[++tot]=(rec){y,cnt,2}; 51 } 52 cdq(1,tot); 53 for(rg int i=1;i<=cnt;i++) printf("%d\n",ans[i]); 54 } 55