BZOJ4066 简单题
2016-05-24 21:05
232 查看
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
41 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
Sample Output
35
数据规模和约定
1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
正解:kd-tree
解题报告:
大概题意是给你一个二维的图,每次给一个点加上一个数,查询某个矩阵中的和,强制在线
kd-tree第二发题,又是一道模板水题 kd-tree最喜欢的强制在线。其实如果可以离线的话我可以用整体二分。
回到正题,一看数据范围n<=500000,操作数<=200000,显然500000*500000的空间是很令人愉快的,所以另辟蹊径。
根据kd-tree思想,我们划分二维空间,搞出一棵神奇的二维二叉搜索树(kd-tree的本质),每次插入结点就直接按二叉搜索树的规则插入,查询也是按二叉搜索树的规则来查询。然而注意到这种做法在这道题是可以被卡的,比如说全挂在了一边,退化成链(变态出题人)
所以我们可以每插入5000个结点就重构一次树,把树的形态重新改变一下,这样就可以保证复杂度了。在BZOJ上跑得太慢了,只有rank50多。
具体实现看代码。
//It is made by jump~ #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #ifdef WIN32 #define OT "%I64d" #else #define OT "%lld" #endif using namespace std; typedef long long LL; const int MAXN = 200011; const int MOD = 5000; int n,m; int ans; int k1,k2,val; int lx,ly,rx,ry; int root; int nowD; struct node{ int d[2],Min[2],Max[2]; int sum,w; int ch[2]; }t[MAXN]; inline int getint() { int w=0,q=0; char c=getchar(); while((c<'0' || c>'9') && c!='-') c=getchar(); if (c=='-') q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; } inline void update(int now){ t[now].sum=t[now].w; for(int i=0;i<=1;i++) { if(t[now].ch[i]) { t[now].sum+=t[ t[now].ch[i] ].sum; if(t[ t[now].ch[i] ].Min[0] < t[now].Min[0]) t[now].Min[0]=t[ t[now].ch[i] ].Min[0]; if(t[ t[now].ch[i] ].Max[0] > t[now].Max[0]) t[now].Max[0]=t[ t[now].ch[i] ].Max[0]; if(t[ t[now].ch[i] ].Min[1] < t[now].Min[1]) t[now].Min[1]=t[ t[now].ch[i] ].Min[1]; if(t[ t[now].ch[i] ].Max[1] > t[now].Max[1]) t[now].Max[1]=t[ t[now].ch[i] ].Max[1]; } } } inline void kd_insert(int root,int D){ int direc=(t .d[D]>t[root].d[D]); if(t[root].ch[direc]) kd_insert(t[root].ch[direc],D^1); else t[root].ch[direc]=n; update(root); } inline void kd_query(int now){ 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; for(int i=0;i<=1;i++) { if(t[now].ch[i]){ 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) { 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; else kd_query(t[now].ch[i]); } } } } inline bool cmp(node q,node qq){ if(q.d[nowD]==qq.d[nowD]) return q.d[nowD^1]<qq.d[nowD^1]; return q.d[nowD]<qq.d[nowD]; } inline int rebuild(int l,int r,int D){ int mid=(l+r)/2; nowD=D; nth_element(t+l+1,t+mid+1,t+r+1,cmp); //t[mid].sum=t[mid].w; t[mid].Min[0]=t[mid].Max[0]=t[mid].d[0]; t[mid].Min[1]=t[mid].Max[1]=t[mid].d[1]; if(l!=mid) t[mid].ch[0]=rebuild(l,mid-1,D^1); if(mid!=r) t[mid].ch[1]=rebuild(mid+1,r,D^1); update(mid); return mid; } inline void solve(){ int ljh; root=1; while(1){ ljh=getint(); if(ljh==3) break; else if(ljh==1) { k1=getint();k2=getint();val=getint(); k1=k1^ans; k2=k2^ans; val=val^ans; n++; t .Min[0]=t .Max[0]=t .d[0]=k1; t .Min[1]=t .Max[1]=t .d[1]=k2; t .w=t .sum=val; if(n>1){ if(n%MOD==0) { for(int i=1;i<=n;i++) t[i].ch[0]=t[i].ch[1]=0; root=rebuild(1,n,0); } else kd_insert(root,0); } } else { lx=getint();ly=getint();rx=getint();ry=getint(); lx=lx^ans; ly=ly^ans; rx=rx^ans; ry=ry^ans; ans=0; if(n) kd_query(root); printf("%d\n",ans); } } } int main() { m=getint(); solve(); return 0; }
相关文章推荐
- mysql 利用binlog增量备份,还原实例
- CLR Via C# 第五章(基元类型,引用类型与值类型)(2)——读书笔记
- Python -- if while for 语句
- Centos6 安装 smplayer
- 【Leetcode】Minimum Window Substring
- HDU1012 u Calculate e
- netty 学习 (3)发送对象
- Broadcast和ContentProvider
- leetcode笔记—关于动态规划
- Spring学习(五)Spring开发包介绍
- RxJava 操作符flatmap
- HDFS Federation (读书笔记)
- C++第六次实验——作业
- C++类对象指针
- Java 数组 foreach
- GEEK编程练习— —三数求和
- UESTC 1253 阿里巴巴和n个大盗(博弈)
- c++实验6数组合并
- Linux下redis的安装
- Codeforces Round #326 (Div. 2)-Duff and Meat