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
HINT
数据规模和约定
1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
样例解释见OJ2683
新加数据一组,但未重测----2015.05.24
正解:$kd-tree$。
省选前发现这题卡空间,当时还不会做。然而现在学了$kd-tree$,就简单多了。。
不过我还是调了好久,主要是一些边界条件错误和两矩形相交的剪枝写萎了。。
注意每加入一定的点就要重构$kd-tree$,因为丧心病狂的出题人可能会卡你。。
还有就是重构的时候左右儿子一定要先清空,子树和也要赋值成单点值。
判断两矩形相交,只要有一维不相交那么两矩形就是不相交的,我就是因为这里才$T$的。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (400010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define fi01() for (RG int i=0;i<=1;++i) 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 int K,n,rt,sz,opt,ans; 24 25 struct node{ 26 27 int a[2],mn[2],mx[2],l,r,v,sum; 28 29 bool operator < (const node &t) const{ 30 return a[K]<t.a[K] || (a[K]==t.a[K] && a[K^1]<t.a[K^1]); 31 } 32 33 }t[N],S,S1,S2; 34 35 il int gi(){ 36 RG int x=0,q=1; RG char ch=getchar(); 37 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 38 if (ch=='-') q=-1,ch=getchar(); 39 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 40 return q*x; 41 } 42 43 il void merge(RG int x){ 44 fi01(){ 45 if (t[x].l){ 46 t[x].mn[i]=min(t[x].mn[i],t[t[x].l].mn[i]); 47 t[x].mx[i]=max(t[x].mx[i],t[t[x].l].mx[i]); 48 } 49 if (t[x].r){ 50 t[x].mn[i]=min(t[x].mn[i],t[t[x].r].mn[i]); 51 t[x].mx[i]=max(t[x].mx[i],t[t[x].r].mx[i]); 52 } 53 } 54 t[x].sum=t[t[x].l].sum+t[t[x].r].sum+t[x].v; return; 55 } 56 57 il int rebuild(RG int l,RG int r,RG int p){ 58 K=p; RG int mid=(l+r)>>1; nth_element(t+l,t+mid,t+r+1); 59 fi01() t[mid].mn[i]=t[mid].mx[i]=t[mid].a[i]; 60 t[mid].sum=t[mid].v,t[mid].l=t[mid].r=0; 61 if (l<mid) t[mid].l=rebuild(l,mid-1,p^1); 62 if (r>mid) t[mid].r=rebuild(mid+1,r,p^1); 63 merge(mid); return mid; 64 } 65 66 il void insert(RG int x,RG int p){ 67 K=p; 68 if (S<t[x]){ if (!t[x].l) t[t[x].l=++sz]=S; else insert(t[x].l,p^1); } 69 else{ if (!t[x].r) t[t[x].r=++sz]=S; else insert(t[x].r,p^1); } 70 merge(x); return; 71 } 72 73 il int sa(node a,node b){ 74 fi01() if (b.mn[i]>a.a[i] || a.a[i]>b.mx[i]) return 0; return 1; 75 } 76 77 il int sb(node a,node b){ 78 fi01() if (b.mn[i]>a.mn[i] || a.mx[i]>b.mx[i]) return 0; return 1; 79 } 80 81 il int sc(node a,node b){ 82 fi01() if (a.mx[i]<b.mn[i] || a.mn[i]>b.mx[i]) return 0; return 1; 83 } 84 85 il void query(RG int x){ 86 if (!x) return; if (sa(t[x],S)) ans+=t[x].v; 87 if (t[x].l){ 88 if (sb(t[t[x].l],S)) ans+=t[t[x].l].sum; 89 else if (sc(t[t[x].l],S)) query(t[x].l); 90 } 91 if (t[x].r){ 92 if (sb(t[t[x].r],S)) ans+=t[t[x].r].sum; 93 else if (sc(t[t[x].r],S)) query(t[x].r); 94 } 95 return; 96 } 97 98 il void work(){ 99 n=gi(); 100 while (1){ 101 opt=gi(); if (opt==3) break; 102 if (opt==1){ 103 S.a[0]=gi()^ans,S.a[1]=gi()^ans,S.v=gi()^ans; 104 fi01() S.mn[i]=S.mx[i]=S.a[i]; S.sum=S.v,S.l=S.r=0; 105 if (!sz) t[rt=++sz]=S; else insert(rt,0); 106 if (sz%5000==0) rt=rebuild(1,sz,0); 107 } 108 if (opt==2){ 109 S1.a[0]=gi()^ans,S1.a[1]=gi()^ans; 110 S2.a[0]=gi()^ans,S2.a[1]=gi()^ans; 111 if (S1.a[0]>S2.a[0]) swap(S1.a[0],S2.a[0]); 112 if (S1.a[1]>S2.a[1]) swap(S1.a[1],S2.a[1]); 113 fi01() S.mn[i]=S1.a[i],S.mx[i]=S2.a[i]; 114 ans=0,query(rt),printf("%d\n",ans); 115 } 116 } 117 return; 118 } 119 120 int main(){ 121 File("simple"); 122 work(); 123 return 0; 124 }