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。
接下来每行一个操作。每条命令除第一个数字之外,
均要异或上一次输出的答案last_ans,初始时last_ans=0。
Output
对于每个2操作,输出一个对应的答案。
Sample Input
4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
Sample Output
3
5
5
HINT
1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
题解:
K-Dtree模板。
用了一下替罪羊树的思想,插入几个数就拍平重建一下。
1 //Never forget why you start 2 #include<iostream> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<algorithm> 8 #define y1 yy 9 using namespace std; 10 typedef long long lol; 11 lol read(){ 12 lol ans=0,f=1;char i=getchar(); 13 while(i<‘0‘||i>‘9‘){if(i==‘-‘)f=-1;i=getchar();} 14 while(i>=‘0‘&&i<=‘9‘){ans=ans*10+i-‘0‘;i=getchar();} 15 return ans*f; 16 } 17 int n,D; 18 lol last; 19 struct point{ 20 int d[2],mmax[2],mmin[2],v,l,r; 21 lol sum; 22 friend bool operator == (const point a,const point b){ 23 return a.d[0]==b.d[0]&&a.d[1]==b.d[1]; 24 } 25 friend bool operator < (const point a,const point b){ 26 return a.d[D]<b.d[D]; 27 } 28 }p[200005]; 29 bool in(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){ 30 return x1<=X1&&y1<=Y1&&X2<=x2&&Y2<=y2; 31 } 32 bool out(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){ 33 return x1>X2||x2<X1||y1>Y2||y2<Y1; 34 } 35 struct kdtree{ 36 point t[200005],now; 37 int root,cnt; 38 void push_up(int rt){ 39 int l=t[rt].l,r=t[rt].r; 40 for(int i=0;i<2;i++){ 41 t[rt].mmin[i]=t[rt].mmax[i]=t[rt].d[i]; 42 if(l)t[rt].mmin[i]=min(t[rt].mmin[i],t[l].mmin[i]); 43 if(l)t[rt].mmax[i]=max(t[rt].mmax[i],t[l].mmax[i]); 44 if(r)t[rt].mmin[i]=min(t[rt].mmin[i],t[r].mmin[i]); 45 if(r)t[rt].mmax[i]=max(t[rt].mmax[i],t[r].mmax[i]); 46 } 47 t[rt].sum=t[rt].v+t[l].sum+t[r].sum; 48 } 49 void insert(int &rt,bool D){ 50 if(!rt){ 51 rt=++cnt; 52 t[rt].d[0]=t[rt].mmin[0]=t[rt].mmax[0]=now.d[0]; 53 t[rt].d[1]=t[rt].mmin[1]=t[rt].mmax[1]=now.d[1]; 54 } 55 if(now==t[rt]){ 56 t[rt].v+=now.v; 57 t[rt].sum+=now.v; 58 return; 59 } 60 if(now.d[D]<t[rt].d[D])insert(t[rt].l,D^1); 61 else insert(t[rt].r,D^1); 62 push_up(rt); 63 } 64 lol query(int rt,int x1,int y1,int x2,int y2){ 65 if(!rt)return 0; 66 lol tmp=0; 67 if(in(x1,y1,x2,y2,t[rt].mmin[0],t[rt].mmin[1],t[rt].mmax[0],t[rt].mmax[1]))return t[rt].sum; 68 if(out(x1,y1,x2,y2,t[rt].mmin[0],t[rt].mmin[1],t[rt].mmax[0],t[rt].mmax[1]))return 0; 69 if(in(x1,y1,x2,y2,t[rt].d[0],t[rt].d[1],t[rt].d[0],t[rt].d[1]))tmp+=t[rt].v; 70 tmp+=query(t[rt].l,x1,y1,x2,y2)+query(t[rt].r,x1,y1,x2,y2); 71 return tmp; 72 } 73 int rebuild(int l,int r,bool f){ 74 if(l>r)return 0; 75 int mid=(l+r)>>1; 76 D=f;nth_element(p+l,p+mid,p+r+1); 77 t[mid]=p[mid]; 78 t[mid].l=rebuild(l,mid-1,f^1); 79 t[mid].r=rebuild(mid+1,r,f^1); 80 push_up(mid); 81 return mid; 82 } 83 }T; 84 int main(){ 85 int i,j,x1,y1,x2,y2,m=10000; 86 n=read(); 87 while(1){ 88 i=read(); 89 if(i==3)break; 90 x1=read()^last;y1=read()^last; 91 if(i==1){ 92 j=read()^last;T.now.d[0]=x1;T.now.d[1]=y1; 93 T.now.v=T.now.sum=j; 94 T.insert(T.root,0); 95 if(T.cnt==m){ 96 for(int i=1;i<=T.cnt;i++)p[i]=T.t[i]; 97 T.root=T.rebuild(1,T.cnt,0); 98 m+=10000; 99 } 100 } 101 if(i==2){ 102 x2=read()^last;y2=read()^last; 103 printf("%lld\n",last=T.query(T.root,x1,y1,x2,y2)); 104 } 105 } 106 return 0; 107 }