题意:单点更新,大矩阵(\(n*n,n≤10^5\))求和

二维的KD树能使最坏情况不高于\(O(N\sqrt{N})\)

核心在于query时判断当前子树维护的区间是否有交集/当前子节点是否在块中,然后暴力....

然后跑30s的KD树...

维护size的重构方法不知为何T了,借鉴了hzwer的按数目重构

一个微小的工作是如果更新时点相同那就直接合并,不要另开(虽然还是可以轻易地被卡)

T了三天三夜的题总算告一段落了

  1. #include<bits/stdc++.h>
  2. #define rep(i,j,k) for(register int i=j;i<=k;i++)
  3. #define rrep(i,j,k) for(register int i=j;i>=k;i--)
  4. #define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
  5. #define print(a) printf("%lld",(ll)(a))
  6. #define println(a) printf("%lld\n",(ll)(a))
  7. #define printbk(a) printf("%lld ",(ll)(a))
  8. using namespace std;
  9. const int MAXN = 2e5+11;
  10. const int INF = 0x7fffffff;
  11. typedef long long ll;
  12. ll read(){
  13. ll x=0,f=1;register char ch=getchar();
  14. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  15. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  16. return x*f;
  17. }
  18. int D;
  19. struct Point{
  20. int x[2],val;
  21. bool operator < (const Point &rhs) const{
  22. return x[D]<rhs.x[D];
  23. }
  24. };
  25. //struct REC{
  26. // int x[2],val;
  27. // bool operator < (const REC &rhs) const{
  28. // return x[D]<rhs.x[D];
  29. // }
  30. //}rec[MAXN];
  31. struct KD{
  32. int son[MAXN][2],lx[MAXN][2],rx[MAXN][2];
  33. int size[MAXN];
  34. ll sum[MAXN];
  35. Point p[MAXN];
  36. int root,tot;
  37. void pu(int o){
  38. int lc=son[o][0],rc=son[o][1];
  39. rep(i,0,1){
  40. lx[o][i]=rx[o][i]=p[o].x[i];
  41. if(lc){
  42. if(lx[lc][i]<lx[o][i]) lx[o][i]=lx[lc][i];
  43. if(rx[lc][i]>rx[o][i]) rx[o][i]=rx[lc][i];
  44. }
  45. if(rc){
  46. if(lx[rc][i]<lx[o][i]) lx[o][i]=lx[rc][i];
  47. if(rx[rc][i]>rx[o][i]) rx[o][i]=rx[rc][i];
  48. }
  49. }
  50. sum[o]=p[o].val+sum[lc]+sum[rc];
  51. size[o]=1+size[lc]+size[rc];
  52. }
  53. void init(){
  54. root=tot=D=0;
  55. }
  56. bool ok(int o){
  57. int lc=son[o][0],rc=son[o][1];
  58. int ls=size[lc]<<2;
  59. int rs=size[rc]<<2;
  60. int sz=size[o]<<1|1;
  61. return ls<=sz&&rs<=sz;
  62. }
  63. void insert(int &o,int now,int x,int y,int v){
  64. if(!o){
  65. o=++tot;
  66. p[o].x[0]=lx[o][0]=rx[o][0]=x;
  67. p[o].x[1]=lx[o][1]=rx[o][1]=y;
  68. p[o].val=sum[o]=v;size[o]=1;
  69. son[o][0]=son[o][1]=0;
  70. return;
  71. }else if(p[o].x[0]==x&&p[o].x[1]==y){
  72. p[o].val+=v;sum[o]+=v;
  73. return;
  74. }else if(now==0){
  75. if(x<p[o].x[0]) insert(son[o][0],1,x,y,v);
  76. else insert(son[o][1],1,x,y,v);
  77. }else{
  78. if(y<p[o].x[1]) insert(son[o][0],0,x,y,v);
  79. else insert(son[o][1],0,x,y,v);
  80. }
  81. pu(o);
  82. }
  83. bool inside(int x_1,int y_1,int x_2,int y_2,int X1,int Y1,int X2,int Y2){
  84. return x_1<=X1&&X2<=x_2&&y_1<=Y1&&Y2<=y_2;
  85. }
  86. bool outside(int x_1,int y_1,int x_2,int y_2,int X1,int Y1,int X2,int Y2){
  87. return x_1>X2||x_2<X1||y_1>Y2||y_2<Y1;
  88. }
  89. ll query(int o,int x_1,int y_1,int x_2,int y_2){
  90. if(!o) return 0;
  91. #define RECT lx[o][0],lx[o][1],rx[o][0],rx[o][1]
  92. #define POT p[o].x[0],p[o].x[1],p[o].x[0],p[o].x[1]
  93. if(inside(x_1,y_1,x_2,y_2,RECT)) return sum[o];
  94. if(outside(x_1,y_1,x_2,y_2,RECT)) return 0;
  95. ll res=0;
  96. if(inside(x_1,y_1,x_2,y_2,POT)) res=p[o].val;
  97. return res+query(son[o][0],x_1,y_1,x_2,y_2)+query(son[o][1],x_1,y_1,x_2,y_2);
  98. }
  99. int rebuild(int now,int l,int r){
  100. int mid=l+r>>1; son[mid][0]=son[mid][1]=0;
  101. D=now; nth_element(p+l,p+mid,p+r+1);
  102. // p[mid].x[0]=rec[mid].x[0];p[mid].x[1]=rec[mid].x[1];
  103. // val[mid]=sum[mid]=rec[mid].val;size[mid]=1;
  104. sum[mid]=p[mid].val; size[mid]=1;
  105. lx[mid][0]=rx[mid][0]=p[mid].x[0];
  106. lx[mid][1]=rx[mid][1]=p[mid].x[1];
  107. if(l<mid) son[mid][0]=rebuild(now^1,l,mid-1);
  108. if(r>mid) son[mid][1]=rebuild(now^1,mid+1,r);
  109. pu(mid);
  110. return mid;
  111. }
  112. void recycle(){
  113. root=rebuild(0,1,tot);
  114. }
  115. }kd;
  116. int main(){
  117. ll n,lastans=0;
  118. while(cin>>n){
  119. kd.init();
  120. int m=10000;
  121. while(1){
  122. int op=read();
  123. if(op==3) break;
  124. else if(op==1){
  125. int x=read()^lastans;
  126. int y=read()^lastans;
  127. int v=read()^lastans;
  128. kd.insert(kd.root,0,x,y,v);
  129. if(kd.tot==m) kd.recycle(),m+=10000;
  130. }else{
  131. int x_1=read()^lastans;
  132. int y_1=read()^lastans;
  133. int x_2=read()^lastans;
  134. int y_2=read()^lastans;
  135. lastans=kd.query(kd.root,x_1,y_1,x_2,y_2);
  136. println(lastans);
  137. }
  138. }
  139. }
  140. return 0;
  141. }

顺便贴上按size平衡因子维护的版本(TLE,不打算改了)

  1. #include<bits/stdc++.h>
  2. #define rep(i,j,k) for(register int i=j;i<=k;i++)
  3. #define rrep(i,j,k) for(register int i=j;i>=k;i--)
  4. #define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
  5. #define print(a) printf("%lld",(ll)(a))
  6. #define println(a) printf("%lld\n",(ll)(a))
  7. #define printbk(a) printf("%lld ",(ll)(a))
  8. using namespace std;
  9. const int MAXN = 2e5+11;
  10. const int INF = 0x7fffffff;
  11. typedef long long ll;
  12. ll read(){
  13. ll x=0,f=1;register char ch=getchar();
  14. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  15. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  16. return x*f;
  17. }
  18. int D;
  19. struct Point{
  20. int x[2],val;
  21. bool operator < (const Point &rhs) const{
  22. return x[D]<rhs.x[D];
  23. }
  24. }p[MAXN];
  25. struct KD{
  26. int son[MAXN][2],lx[MAXN][2],rx[MAXN][2];
  27. int size[MAXN];
  28. ll sum[MAXN];
  29. int root,tot;
  30. struct REC{
  31. int id;
  32. bool operator < (const REC &rhs) const{
  33. return p[id]<p[rhs.id];
  34. }
  35. }rec[MAXN];int cnt;
  36. void dfs(int o){
  37. if(!o) return;
  38. dfs(son[o][0]);
  39. rec[++cnt].id=o;
  40. dfs(son[o][1]);
  41. }
  42. void pu(int o){
  43. int lc=son[o][0],rc=son[o][1];
  44. rep(i,0,1){
  45. lx[o][i]=rx[o][i]=p[o].x[i];
  46. if(lc){
  47. if(lx[lc][i]<lx[o][i]) lx[o][i]=lx[lc][i];
  48. if(rx[lc][i]>rx[o][i]) rx[o][i]=rx[lc][i];
  49. }
  50. if(rc){
  51. if(lx[rc][i]<lx[o][i]) lx[o][i]=lx[rc][i];
  52. if(rx[rc][i]>rx[o][i]) rx[o][i]=rx[rc][i];
  53. }
  54. }
  55. sum[o]=p[o].val+sum[lc]+sum[rc];
  56. size[o]=1+size[lc]+size[rc];
  57. }
  58. void init(){
  59. root=tot=D=0;
  60. }
  61. bool ok(int o){
  62. int lc=son[o][0],rc=son[o][1];
  63. int ls=size[lc]<<2;
  64. int rs=size[rc]<<2;
  65. int sz=size[o]<<1|1;
  66. return ls<=sz&&rs<=sz;
  67. }
  68. void insert(int &o,int now,int x,int y,int v){
  69. if(!o){
  70. o=++tot;
  71. p[o].x[0]=lx[o][0]=rx[o][0]=x;
  72. p[o].x[1]=lx[o][1]=rx[o][1]=y;
  73. p[o].val=sum[o]=v;size[o]=1;
  74. son[o][0]=son[o][1]=0;
  75. return;
  76. }else if(p[o].x[0]==x&&p[o].x[1]==y){
  77. p[o].val+=v;sum[o]+=v;
  78. return;
  79. }else if(now==0){
  80. if(x<p[o].x[0]) insert(son[o][0],1,x,y,v);
  81. else insert(son[o][1],1,x,y,v);
  82. }else{
  83. if(y<p[o].x[1]) insert(son[o][0],0,x,y,v);
  84. else insert(son[o][1],0,x,y,v);
  85. }
  86. pu(o);
  87. if(size[o]>1000&&!ok(o)) rebuild(o);
  88. }
  89. bool inside(int x_1,int y_1,int x_2,int y_2,int X1,int Y1,int X2,int Y2){
  90. return x_1<=X1&&X2<=x_2&&y_1<=Y1&&Y2<=y_2;
  91. }
  92. bool outside(int x_1,int y_1,int x_2,int y_2,int X1,int Y1,int X2,int Y2){
  93. return x_1>X2||x_2<X1||y_1>Y2||y_2<Y1;
  94. }
  95. ll query(int o,int x_1,int y_1,int x_2,int y_2){
  96. if(!o) return 0;
  97. #define RECT lx[o][0],lx[o][1],rx[o][0],rx[o][1]
  98. #define POT p[o].x[0],p[o].x[1],p[o].x[0],p[o].x[1]
  99. if(inside(x_1,y_1,x_2,y_2,RECT)) return sum[o];
  100. if(outside(x_1,y_1,x_2,y_2,RECT)) return 0;
  101. ll res=0;
  102. if(inside(x_1,y_1,x_2,y_2,POT)) res=p[o].val;
  103. return res+query(son[o][0],x_1,y_1,x_2,y_2)+query(son[o][1],x_1,y_1,x_2,y_2);
  104. }
  105. int rebuild(int now,int l,int r){
  106. int mid=l+r>>1;
  107. D=now; nth_element(rec+l,rec+mid,rec+r+1);
  108. int o=rec[mid].id;
  109. sum[o]=p[o].val; size[o]=1;
  110. son[o][0]=son[o][1]=0;
  111. lx[o][0]=rx[o][0]=p[o].x[0];
  112. lx[o][1]=rx[o][1]=p[o].x[1];
  113. if(l<mid) son[o][0]=rebuild(now^1,l,mid-1);
  114. if(r>mid) son[o][1]=rebuild(now^1,mid+1,r);
  115. pu(o);
  116. return o;
  117. }
  118. void rebuild(int &o){
  119. cnt=0;
  120. dfs(o);
  121. o=rebuild(0,1,cnt);
  122. }
  123. }kd;
  124. int main(){
  125. ll n,lastans=0;
  126. while(cin>>n){
  127. kd.init();
  128. while(1){
  129. int op=read();
  130. if(op==3) break;
  131. else if(op==1){
  132. int x=read()^lastans;
  133. int y=read()^lastans;
  134. int v=read()^lastans;
  135. kd.insert(kd.root,0,x,y,v);
  136. }else{
  137. int x_1=read()^lastans;
  138. int y_1=read()^lastans;
  139. int x_2=read()^lastans;
  140. int y_2=read()^lastans;
  141. lastans=kd.query(kd.root,x_1,y_1,x_2,y_2);
  142. println(lastans);
  143. }
  144. }
  145. }
  146. return 0;
  147. }

BZOJ - 4066 KD树 范围计数 暴力重构的更多相关文章

  1. BZOJ - 3489 KD树 范围计数 空间思维转换

    题意:给定数列\(a[1...n]\),\(Q\)次查询\([L,R]\)中只出现一次的最大值 这道题的做法比较劲.. 对每个元素构造三维空间的点\((i,pre[i],next[i])\),查询\( ...

  2. bzoj 3489: A simple rmq problem k-d树思想大暴力

    3489: A simple rmq problem Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 551  Solved: 170[Submit][ ...

  3. BZOJ 1211: [HNOI2004]树的计数( 组合数学 )

    知道prufer序列就能写...就是求个可重集的排列...先判掉奇怪的情况, 然后答案是(N-2)!/π(d[i]-1)! -------------------------------------- ...

  4. bzoj 1211: [HNOI2004]树的计数 -- purfer序列

    1211: [HNOI2004]树的计数 Time Limit: 10 Sec  Memory Limit: 162 MB Description 一个有n个结点的树,设它的结点分别为v1, v2, ...

  5. BZOJ - 2648 KD树 最近点查询

    省赛后躺尸几天又回来更新了,内容是说好的KD树.. 具体操作从代码中感受一下 感觉已经把KD树尽量封装好了(虽然全局的D看着极不顺眼) 需要注意的是估值函数的判断条件 #include<bits ...

  6. 数据结构(平衡树,树分治,暴力重构):WC 2014 紫荆花之恋

    [题目描述] 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这棵大树实际上是一个带权 ...

  7. BZOJ 1211 HNOI2004 树的计数 Prufer序列

    题目大意:给定一棵树中全部点的度数,求有多少种可能的树 Prufer序列.详细參考[HNOI2008]明明的烦恼 直接乘会爆long long,所以先把每一个数分解质因数.把质因数的次数相加相减.然后 ...

  8. bzoj 3244: [Noi2013]树的计数

    Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...

  9. BZOJ 1211[HNOI2004]树的计数 - prufer数列

    描述 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要输出满足d(vi) ...

随机推荐

  1. oracle 创建表 外键约束

    create table usertable( id int primary key, username ) not null, birthday date, sex ), address ) ); ...

  2. 4-fiddler抓包中文乱码:

    接受到的html被压缩了,要解压,在工具栏有decode

  3. Spring--入门第二天

    一.通过工厂方法配置bean Spring 中有两种类型的 Bean, 一种是普通Bean, 另一种是工厂Bean, 即FactoryBean. 工厂 Bean 跟普通Bean不同, 其返回的对象不是 ...

  4. 基于.Net平台常用的组件和框架整理

    转载自:http://www.cnblogs.com/hgmyz/p/5313983.html 基于转载进行补充 RPC框架: RPC:远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而 ...

  5. Mathematical optimization数学上的最优化

    https://en.wikipedia.org/wiki/Mathematical_optimization In mathematics, computer science and operati ...

  6. linq to sql 实现左(右)连接,那个方法是对的,该怎么处理

    linq to sql 实现左(右)连接,那个方法是对的var query2 = from tb0 in db.table_0  join tb1 in db.table_1 on table_0.关 ...

  7. 如何在sqlserver 的函数或存储过程中抛出异常。

    raiserror 的作用: raiserror 是用于抛出一个错误.[ 以下资料来源于sql server 2005的帮助 ] 其语法如下: RAISERROR ( { msg_id | msg_s ...

  8. POJ - 3984 迷宫问题 BFS求具体路径坐标

    迷宫问题 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, ...

  9. dynamic的好处

    dynamic 可在反射.json反序列化时使用.已达到减少代码量的效果.看代码 using System; namespace ConsoleApp2 { class Program { stati ...

  10. 【大数据之数据仓库】GreenPlum优化器对比测试

    在< [大数据之数据仓库]选型流水记>一文中有提及,当时没有测试GreenPlum的quicklz压缩算法和ORCA查询优化器,考虑到quicklz压缩算法因为版权问题不会开源(详情请参阅 ...