[BZOJ 4066]简单题

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范围内并且解码之后数据仍合法。

题解:

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 }

 

posted @ 2018-01-23 21:46  kakakakakaka  阅读(186)  评论(0编辑  收藏  举报

Never forget why you start

//鼠标爆炸特效