BZOJ4066 简单题
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
数据规模和约定
1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
正解:kd-tree
解题报告:
大概题意是给你一个二维的图,每次给一个点加上一个数,查询某个矩阵中的和,强制在线
kd-tree第二发题,又是一道模板水题 kd-tree最喜欢的强制在线。其实如果可以离线的话我可以用整体二分。
回到正题,一看数据范围n<=500000,操作数<=200000,显然500000*500000的空间是很令人愉快的,所以另辟蹊径。
根据kd-tree思想,我们划分二维空间,搞出一棵神奇的二维二叉搜索树(kd-tree的本质),每次插入结点就直接按二叉搜索树的规则插入,查询也是按二叉搜索树的规则来查询。然而注意到这种做法在这道题是可以被卡的,比如说全挂在了一边,退化成链(变态出题人)
所以我们可以每插入5000个结点就重构一次树,把树的形态重新改变一下,这样就可以保证复杂度了。在BZOJ上跑得太慢了,只有rank50多。
具体实现看代码。
1 //It is made by jump~ 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector> 10 #include <queue> 11 #include <map> 12 #ifdef WIN32 13 #define OT "%I64d" 14 #else 15 #define OT "%lld" 16 #endif 17 using namespace std; 18 typedef long long LL; 19 const int MAXN = 200011; 20 const int MOD = 5000; 21 int n,m; 22 int ans; 23 int k1,k2,val; 24 int lx,ly,rx,ry; 25 int root; 26 int nowD; 27 28 struct node{ 29 int d[2],Min[2],Max[2]; 30 int sum,w; 31 int ch[2]; 32 }t[MAXN]; 33 34 inline int getint() 35 { 36 int w=0,q=0; 37 char c=getchar(); 38 while((c<'0' || c>'9') && c!='-') c=getchar(); 39 if (c=='-') q=1, c=getchar(); 40 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); 41 return q ? -w : w; 42 } 43 44 inline void update(int now){ 45 t[now].sum=t[now].w; 46 for(int i=0;i<=1;i++) { 47 if(t[now].ch[i]) { 48 t[now].sum+=t[ t[now].ch[i] ].sum; 49 if(t[ t[now].ch[i] ].Min[0] < t[now].Min[0]) t[now].Min[0]=t[ t[now].ch[i] ].Min[0]; 50 if(t[ t[now].ch[i] ].Max[0] > t[now].Max[0]) t[now].Max[0]=t[ t[now].ch[i] ].Max[0]; 51 if(t[ t[now].ch[i] ].Min[1] < t[now].Min[1]) t[now].Min[1]=t[ t[now].ch[i] ].Min[1]; 52 if(t[ t[now].ch[i] ].Max[1] > t[now].Max[1]) t[now].Max[1]=t[ t[now].ch[i] ].Max[1]; 53 } 54 } 55 } 56 57 inline void kd_insert(int root,int D){ 58 int direc=(t[n].d[D]>t[root].d[D]); 59 if(t[root].ch[direc]) kd_insert(t[root].ch[direc],D^1); 60 else t[root].ch[direc]=n; 61 update(root); 62 } 63 64 inline void kd_query(int now){ 65 if(t[now].d[0]>=lx && t[now].d[1]>=ly && t[now].d[0]<=rx && t[now].d[1]<=ry) ans+=t[now].w; 66 for(int i=0;i<=1;i++) { 67 if(t[now].ch[i]){ 68 if(t[t[now].ch[i]].Min[0]<=rx&&t[t[now].ch[i]].Max[0]>=lx&&t[t[now].ch[i]].Min[1]<=ry&&t[t[now].ch[i]].Max[1]>=ly) { 69 if(t[t[now].ch[i]].Max[0]<=rx && t[t[now].ch[i]].Min[0]>=lx && t[t[now].ch[i]].Max[1]<=ry && t[t[now].ch[i]].Min[1]>=ly) ans+=t[t[now].ch[i]].sum; 70 else kd_query(t[now].ch[i]); 71 } 72 } 73 } 74 } 75 76 inline bool cmp(node q,node qq){ 77 if(q.d[nowD]==qq.d[nowD]) return q.d[nowD^1]<qq.d[nowD^1]; 78 return q.d[nowD]<qq.d[nowD]; 79 } 80 81 inline int rebuild(int l,int r,int D){ 82 int mid=(l+r)/2; nowD=D; 83 nth_element(t+l+1,t+mid+1,t+r+1,cmp); 84 //t[mid].sum=t[mid].w; 85 t[mid].Min[0]=t[mid].Max[0]=t[mid].d[0]; t[mid].Min[1]=t[mid].Max[1]=t[mid].d[1]; 86 if(l!=mid) t[mid].ch[0]=rebuild(l,mid-1,D^1); 87 if(mid!=r) t[mid].ch[1]=rebuild(mid+1,r,D^1); 88 update(mid); 89 return mid; 90 } 91 92 inline void solve(){ 93 int ljh; root=1; 94 while(1){ 95 ljh=getint(); 96 if(ljh==3) break; 97 else if(ljh==1) { 98 k1=getint();k2=getint();val=getint(); 99 k1=k1^ans; k2=k2^ans; val=val^ans; 100 n++; t[n].Min[0]=t[n].Max[0]=t[n].d[0]=k1; t[n].Min[1]=t[n].Max[1]=t[n].d[1]=k2; t[n].w=t[n].sum=val; 101 if(n>1){ 102 if(n%MOD==0) { 103 for(int i=1;i<=n;i++) t[i].ch[0]=t[i].ch[1]=0; 104 root=rebuild(1,n,0); 105 } 106 else 107 kd_insert(root,0); 108 } 109 } 110 else { 111 lx=getint();ly=getint();rx=getint();ry=getint(); 112 lx=lx^ans; ly=ly^ans; rx=rx^ans; ry=ry^ans; 113 ans=0; 114 if(n) 115 kd_query(root); 116 printf("%d\n",ans); 117 } 118 } 119 } 120 121 int main() 122 { 123 m=getint(); solve(); 124 return 0; 125 }
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!