题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2683
题目大意:二维平面上,单点修改权值,区间询问权值和。
CDQ分治裸题。
话说我今天才学CDQ分治,还想了好久才会写的。
将询问拆成4个操作,CDQ分治搞一搞就好了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define inf 1<<30 6 #define maxn 500005 7 #define maxm 800005 8 using namespace std; 9 int n,tot,m,cnt,pos[maxm],t[maxn],ans[maxm]; 10 struct fuck{int x,y,op,id,v;}e[maxm]; 11 bool comp(fuck a,fuck b){ 12 if(a.x==b.x) return a.y<b.y; 13 return a.x<b.x; 14 } 15 void change(int x,int y){for(int i=x;i<=m;i+=i&-i) t[i]+=y;} 16 int query(int x){int y=0; for(int i=x;i;i-=i&-i) y+=t[i]; return y;} 17 void solve(int l,int r){ 18 if(l==r) return; 19 int mid=(l+r)/2; 20 solve(l,mid); solve(mid+1,r); 21 sort(e+l,e+mid+1,comp); sort(e+mid+1,e+r+1,comp); 22 int i=l,j=mid+1,last=0; 23 while(j<=r){ 24 while(i<=mid&&e[i].op==2) i++; 25 while(j<=r&&e[j].op==1) j++; 26 if(i<=mid&&e[i].x<=e[j].x) change(e[i].y,e[i].v),last=i++; 27 else if(j<=r) ans[e[j].id]+=query(e[j].y),++j; 28 } 29 for(int i=l;i<=last;i++) if(e[i].op==1) change(e[i].y,-e[i].v); 30 } 31 int main(){ 32 scanf("%d",&n); 33 int type,x1,x2,y1,y2; 34 while(1){ 35 scanf("%d",&type); 36 if(type==1){e[++m].op=1; e[m].id=m; scanf("%d%d%d",&e[m].x,&e[m].y,&e[m].v);} 37 else if(type==2){ 38 pos[++cnt]=m; 39 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 40 e[++m].op=2; e[m].x=x2; e[m].y=y2; e[m].id=m; 41 e[++m].op=2; e[m].x=x1-1; e[m].y=y1-1; e[m].id=m; 42 e[++m].op=2; e[m].x=x2; e[m].y=y1-1; e[m].id=m; 43 e[++m].op=2; e[m].x=x1-1; e[m].y=y2; e[m].id=m; 44 } 45 else break; 46 } 47 solve(1,m); 48 for(int i=1;i<=cnt;i++) printf("%d ",ans[pos[i]+1]+ans[pos[i]+2]-ans[pos[i]+3]-ans[pos[i]+4]); 49 return 0; 50 }