標籤:
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
Sample Output
3
5
HINT
資料規模和約定
1<=N<=500000,運算元不超過200000個,記憶體限制20M,保證答案在int範圍內並且解碼之後資料仍合法。
範例解釋見OJ2683
新加資料一組,但未重測—-2015.05.24
我終於過了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
由於記憶體很緊,我們不能用樹套樹來做,但k-d樹還是可以的。
考慮出題人可能將k-d樹的形態搞得很糟糕,我們可以定期重建整棵樹
#include<cstdio>#include<cctype>#include<queue>#include<cstring>#include<algorithm>#define rep(s,t) for(int i=s;i<=t;i++)#define ren for(int i=first[x];i!=-1;i=next[i])using namespace std;inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘; return x*f;}const int maxn=200010;int n,D,lastans;struct Point { int d[2],mx[2],mn[2],v,l,r,sum; bool operator == (const Point& ths) const {return d[0]==ths.d[0]&&d[1]==ths.d[1];} bool operator < (const Point& ths) const {return d[D]<ths.d[D];}}p[maxn];int in(int& x1,int& y1,int& x2,int& y2,int& X1,int& Y1,int& X2,int& Y2) {return x1<=X1&&x2>=X2&&y1<=Y1&&y2>=Y2;}int out(int& x1,int& y1,int& x2,int& y2,int& X1,int& Y1,int& X2,int& Y2) {return x1>X2||x2<X1||y1>Y2||y2<Y1;}struct Kd_Tree { Point t[maxn],now; int rt,cnt; Kd_Tree() {t[0].mn[0]=t[0].mn[1]=2e9;t[0].mx[0]=t[0].mx[1]=-2e9;} void maintain(int k) { int l=t[k].l,r=t[k].r; rep(0,1) t[k].mn[i]=min(t[k].d[i],min(t[l].mn[i],t[r].mn[i])),t[k].mx[i]=max(t[k].d[i],max(t[l].mx[i],t[r].mx[i])); t[k].sum=t[l].sum+t[r].sum+t[k].v; } void insert(int& k,int d) { if(!k) k=++cnt,t[k].d[0]=t[k].mx[0]=t[k].mn[0]=now.d[0],t[k].d[1]=t[k].mx[1]=t[k].mn[1]=now.d[1]; if(now==t[k]) { t[k].v+=now.v;t[k].sum+=now.v; return; } if(now.d[d]<t[k].d[d]) insert(t[k].l,d^1); else insert(t[k].r,d^1); maintain(k); } int query(int k,int x1,int y1,int x2,int y2) { if(!k) return 0; if(in(x1,y1,x2,y2,t[k].mn[0],t[k].mn[1],t[k].mx[0],t[k].mx[1])) return t[k].sum; if(out(x1,y1,x2,y2,t[k].mn[0],t[k].mn[1],t[k].mx[0],t[k].mx[1])) return 0; int ret=0; if(in(x1,y1,x2,y2,t[k].d[0],t[k].d[1],t[k].d[0],t[k].d[1])) ret+=t[k].v; ret+=query(t[k].l,x1,y1,x2,y2)+query(t[k].r,x1,y1,x2,y2); return ret; } int build(int l,int r,int d) { if(l>r) return 0; int mid=l+r>>1;D=d;nth_element(p+l,p+mid,p+r+1); t[mid]=p[mid];t[mid].l=build(l,mid-1,d^1);t[mid].r=build(mid+1,r,d^1); maintain(mid);return mid; }}T;int main() { n=read();int ToT=0; while(1) { int tp=read(); if(tp==3) break; else if(tp==1) { int x=read()^lastans,y=read()^lastans; T.now.d[0]=x;T.now.d[1]=y; T.now.v=T.now.sum=read()^lastans; T.insert(T.rt,0); if(++ToT==7000) { rep(1,T.cnt) p[i]=T.t[i]; T.rt=T.build(1,T.cnt,0);ToT=0; } } else { int x=read()^lastans,y=read()^lastans,x2=read()^lastans,y2=read()^lastans; printf("%d\n",lastans=T.query(T.rt,x,y,x2,y2)); } } return 0;}View Code
BZOJ4066 簡單題