1176: [Balkan2007]Mokia
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 2841 Solved: 1279
[Submit][Status][Discuss]
Description
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
Input
第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小
接下来每行为一下三种输入之一(不包含引号):
"1 x y a"
"2 x1 y1 x2 y2"
"3"
输入1:你需要把(x,y)(第x行第y列)的格子权值增加a
输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出
输入3:表示输入结束
Output
对于每个输入2,输出一行,即输入2的答案
Sample Input
0 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
保证答案不会超过int范围
#include<iostream> #include<cstdio> #include<algorithm> #define maxn 200010 using namespace std; int n,tr[2000010],ans[maxn],T,tot; struct node{ int x,y,op,t,z,belong; bool operator < (const node p)const{ if(x!=p.x)return x<p.x; if(y!=p.y)return y<p.y; return op<p.op; } }q[maxn],tmp[maxn]; void modify(int x,int delta){ while(x<=n){ tr[x]+=delta; x+=x&(-x); } } int query(int x){ int res=0; while(x){ res+=tr[x]; x-=x&(-x); } return res; } void work(int l,int r){ if(l==r)return; int mid=l+r>>1; for(int i=l;i<=r;i++){ if(q[i].t<=mid&&q[i].op==1)modify(q[i].y,q[i].z); if(q[i].t>mid&&q[i].op==2)ans[q[i].belong]+=query(q[i].y)*q[i].z; } for(int i=l;i<=r;i++) if(q[i].t<=mid&&q[i].op==1)modify(q[i].y,-q[i].z); int l1=l,l2=mid+1; for(int i=l;i<=r;i++){ if(q[i].t<=mid)tmp[l1++]=q[i]; else tmp[l2++]=q[i]; } for(int i=l;i<=r;i++)q[i]=tmp[i]; work(l,mid);work(mid+1,r); } int main(){ scanf("%d",&n);scanf("%d",&n); int opt,x,y,z,x1,x2,y1,y2; while(1){ scanf("%d",&opt); if(opt==1){ scanf("%d%d%d",&x,&y,&z); q[++tot].t=tot;q[tot].x=x;q[tot].y=y;q[tot].op=1;q[tot].z=z; } if(opt==2){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); q[++tot].t=tot;q[tot].x=x1-1;q[tot].y=y1-1;q[tot].z=1;q[tot].op=2;q[tot].belong=++T; q[++tot].t=tot;q[tot].x=x1-1;q[tot].y=y2;q[tot].z=-1;q[tot].op=2;q[tot].belong=T; q[++tot].t=tot;q[tot].x=x2;q[tot].y=y1-1;q[tot].z=-1;q[tot].op=2;q[tot].belong=T; q[++tot].t=tot;q[tot].x=x2;q[tot].y=y2;q[tot].z=1;q[tot].op=2;q[tot].belong=T; } if(opt==3)break; } sort(q+1,q+tot+1); work(1,tot); for(int i=1;i<=T;i++)printf("%d\n",ans[i]); return 0; }