[BZOJ 4066]簡單題
阿新 • • 發佈:2019-01-18
+= pac () upd body r+ odi main void
Description
你有一個N*N的棋盤,每個格子內有一個整數,初始時的時候全部為0,現在需要維護兩種操作:
命令 | 參數限制 | 內容 |
---|---|---|
\(1\,x\,y\,A\) | \(1\leqslant x,y\leqslant N\),\(A\)是正整數 | 將格子\(x,y\)裏的數字加上\(A\) |
\(2\,x_1\,y_1\,x_2\,y_2\) | \(1\leqslant x_1\leqslant x_2\leqslant N\\1\leqslant y_1\leqslant y_2\leqslant N\) | 輸出\(x_1\,y_1\,x_2\,y_2\)這個矩形內的數字和 |
\(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
Sample Output
3
5
HINT
\(1\leqslant N\leqslant500000\),操作數不超過200000個,內存限制20M,保證答案在int範圍內並且解碼之後數據仍合法。
20M顯然不能樹套樹……於是我們用一個簡單的數據結構——KD-Tree
自信的寫了一發,交上去TLE……一測數據發現極限數據跑了2m……
完全不會優化啊……還是%%%hzwer
定一個閥值,當KD-Tree插入操作達到這個閥值時,就暴力重構KD-Tree
然後就可以過了……
/*program from Wolfycz*/ #include<cmath> #include<ctime> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 0x7f7f7f7f using namespace std; typedef long long ll; typedef unsigned int ui; typedef unsigned long long ull; inline char gc(){ static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } inline int frd(){ int x=0,f=1; char ch=gc(); for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0'; return x*f; } inline int read(){ int x=0,f=1; char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0'; return x*f; } inline void print(int x){ if (x<0) putchar('-'),x=-x; if (x>9) print(x/10); putchar(x%10+'0'); } const int N=2e5,V=1e4; int T; struct S1{ #define ls(p) tree[p].ls #define rs(p) tree[p].rs struct node{ int v[2],Max[2],Min[2]; int ls,rs,type,val,sum; void insert(int type,int val){v[type]=Min[type]=Max[type]=val;} bool operator <(const node &tis)const{return v[T]<tis.v[T];} }tree[N+10]; int root,tot; int L[2],R[2]; void Add(int *a,int v){a[0]=a[1]=v;} void init(){Add(tree[0].Max,-inf),Add(tree[0].Min,inf);} void updata(int p){ tree[p].Min[0]=min(tree[p].v[0],min(tree[ls(p)].Min[0],tree[rs(p)].Min[0])); tree[p].Min[1]=min(tree[p].v[1],min(tree[ls(p)].Min[1],tree[rs(p)].Min[1])); tree[p].Max[0]=max(tree[p].v[0],max(tree[ls(p)].Max[0],tree[rs(p)].Max[0])); tree[p].Max[1]=max(tree[p].v[1],max(tree[ls(p)].Max[1],tree[rs(p)].Max[1])); } int rebuild(int l,int r,int type){ T=type; int mid=(l+r)>>1,p=mid; nth_element(tree+l,tree+mid,tree+r+1); tree[p].type=type,tree[p].sum=0; tree[p].ls=tree[p].rs=0; if (l<mid) ls(p)=rebuild(l,mid-1,type^1); if (r>mid) rs(p)=rebuild(mid+1,r,type^1); updata(p); tree[p].sum=tree[ls(p)].sum+tree[rs(p)].sum+tree[p].val; return p; } void Modify(int &p,int x,int y,int v){ if (!p){ p=++tot; tree[p].insert(0,x); tree[p].insert(1,y); tree[p].type=rand()&1; tree[p].val=tree[p].sum=v; return; } (tree[p].type?y:x)<tree[p].v[tree[p].type]?Modify(ls(p),x,y,v):Modify(rs(p),x,y,v); updata(p),tree[p].sum=tree[ls(p)].sum+tree[p].val+tree[rs(p)].sum; } int Query(int p){ if (L[0] >tree[p].Max[0]||R[0] <tree[p].Min[0]||L[1] >tree[p].Max[1]||R[1] <tree[p].Min[1]) return 0; if (L[0]<=tree[p].Min[0]&&tree[p].Max[0]<=R[0]&&L[1]<=tree[p].Min[1]&&tree[p].Max[1]<=R[1]) return tree[p].sum; int res=0; if (L[0]<=tree[p].v[0]&&tree[p].v[0]<=R[0]&&L[1]<=tree[p].v[1]&&tree[p].v[1]<=R[1]) res=tree[p].val; res+=Query(ls(p))+Query(rs(p)); return res; } int Query(int x1,int y1,int x2,int y2){ L[0]=x1,R[0]=x2,L[1]=y1,R[1]=y2; return Query(root); } }KDT;//KD-Tree int main(){ srand(time(0)); int n=read(),cnt=0; KDT.init(); for (int lastans=0;;){ int type=read(); if (type==1){ cnt++; int x=read()^lastans,y=read()^lastans,v=read()^lastans; KDT.Modify(KDT.root,x,y,v); if (cnt%V==0) KDT.root=KDT.rebuild(1,KDT.tot,0); } if (type==2){ int x1=read()^lastans,y1=read()^lastans,x2=read()^lastans,y2=read()^lastans; printf("%d\n",lastans=KDT.Query(x1,y1,x2,y2)); } if (type==3) break; } return 0; }
[BZOJ 4066]簡單題