2683: 简单题
Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 1803 Solved: 731
[Submit][Status][Discuss]
Description
你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
命令 |
参数限制 |
内容 |
1 x y A |
1<=x,y<=N,A是正整数 |
将格子x,y里的数字加上A |
2 x1 y1 x2 y2 |
1<=x1<= x2<=N 1<=y1<= y2<=N |
输出x1 y1 x2 y2这个矩形内的数字和 |
3 |
无 |
终止程序 |
Input
输入文件第一行一个正整数N。
接下来每行一个操作。
Output
对于每个2操作,输出一个对应的答案。
Sample Input
4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
3
5
5
HINT
1<=N<=500000,操作数不超过200000个,内存限制20M。
对于100%的数据,操作1中的A不超过2000。
cdq分治三维偏序 三维分别是操作序号,横坐标,纵坐标
把一个询问拆成4个,就变成了处理二维前缀和问题
对横坐标排序,操作序号cdq分治,纵坐标用bit处理
1 #include<bits/stdc++.h> 2 #define N 200005 3 using namespace std; 4 int n,m,t,c[N*3],ans[N]; 5 struct query{ 6 int x,y,v,id,op,bl; 7 bool operator < (const query &b)const{ 8 if(x==b.x&&y==b.y)return id<b.id; 9 return x==b.x?y<b.y:x<b.x; 10 } 11 }q[N<<2],a[N<<2]; 12 13 void add(int x,int y,int v){ 14 if(!x||!y)return; 15 q[++m].x=x;q[m].y=y;q[m].id=m; 16 q[m].op=2;q[m].bl=t;q[m].v=v; 17 } 18 void update(int p,int x){ 19 while(p<=n){ 20 c[p]+=x; 21 p+=p&-p; 22 } 23 } 24 int ask(int x){ 25 int ret=0; 26 while(x){ 27 ret+=c[x]; 28 x-=x&-x; 29 } 30 return ret; 31 } 32 33 void solve(int l,int r){ 34 if(l==r)return; 35 int mid=(l+r)>>1,p1=l,p2=mid+1; 36 for(int i=l;i<=r;++i){ 37 if(q[i].id<=mid&&q[i].op==1)update(q[i].y,q[i].v); 38 if(q[i].id>mid&&q[i].op==2)ans[q[i].bl]+=ask(q[i].y)*q[i].v; 39 } 40 for(int i=l;i<=r;++i) 41 if(q[i].op==1&&q[i].id<=mid)update(q[i].y,-q[i].v); 42 for(int i=l;i<=r;++i){ 43 if(q[i].id<=mid)a[p1++]=q[i]; 44 else a[p2++]=q[i]; 45 } 46 for(int i=l;i<=r;++i)q[i]=a[i]; 47 solve(l,mid);solve(mid+1,r); 48 } 49 int main(){ 50 scanf("%d",&n); 51 while(1){ 52 static int op,x1,x2,y1,y2,v; 53 scanf("%d",&op); 54 if(op==1){ 55 scanf("%d%d%d",&x1,&y1,&v); 56 q[++m].x=x1;q[m].y=y1;q[m].v=v; 57 q[m].id=m;q[m].op=op; 58 } 59 if(op==2){ 60 scanf("%d%d%d%d",&x1,&y1,&x2,&y2);++t; 61 add(x1-1,y1-1,1);add(x2,y2,1); 62 add(x1-1,y2,-1);add(x2,y1-1,-1); 63 } 64 if(op==3)break; 65 } 66 sort(q+1,q+1+m); 67 solve(1,m); 68 for(int i=1;i<=t;i++) 69 printf("%d\n",ans[i]); 70 return 0; 71 }