BZOJ4066 简单题

Posted ljh2000

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

Sample Output

3
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 }

 

以上是关于BZOJ4066 简单题的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj 4066]简单题

[BZOJ2683][BZOJ4066]简单题

Bzoj_4066 简单题

BZOJ4066 简单题

[bzoj4066/2683]简单题_KD-Tree

bzoj4066 简单题