[BZOJ 2989]数列(CDQ 分治)

题面

给定一个长度为n的正整数数列a[i]。

定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|。

2种操作(k都是正整数):

1.Modify x k:将第x个数的值修改为k。

2.Query x k:询问有几个i满足graze(x,i)<=k。因为可持久化数据结构的流行,询问仅要考虑当前数列,还要考虑任意历史版本,即统计任意位置上出现过的任意数值与当前的a[x]的graze值<=k的对数。(某位置多次修改为同样的数值,按多次统计)

分析

据说正解是二进制分组+主席树?

观察到\(|x-y|+|a[x]-a[y]|\),我们想到曼哈顿距离。于是我们把(x,a[x])看作一个二维平面上的点,而查询的是到平面上一定点距离<=k的点的个数。同时这样还避免了可持久化的问题,因为把a[x]修改成k,相当于新建了一个点。

到平面上一定点曼哈顿距离=k的点的集合(曼哈顿距离下的圆)是一个斜45°,边长为\(\frac{\sqrt{2}}{2}k\)的正方形。我们求的答案就是这个正方形里的点的个数

[图片转载自https://www.cnblogs.com/SGCollin/p/9636955.html]

这样的点距离不太好求。但是我们知道切比雪夫距离下的圆是一个四边都平行坐标轴的正方形。因此我们可以把曼哈顿距离转成对应的切比雪夫距离。注:\((x_1,y_1)和(x_2,y_2)的切比雪夫距离是max(|x_1-x_2|,|y_1-y_2|)\)

考虑把两个点转化成\((x_1+y_1,x_1-y_1),(x_2+y_2,x_2-y_2)\),容易发现新点的切比雪夫距离和原来点的曼哈顿距离相同.

那么我们只要把询问和修改的每个点都转成(x+y,x-y)的形式,然后问题就变成在把原来查询的正方形转换后新的正方形里点的个数。由于边都平行于坐标轴,这是一个经典的三维偏序问题,详情可参考[BZOJ 2683] 简单题 (CDQ分治)

代码

  1. //首先把询问转成曼哈顿距离,(i,a[i])看成一个点
  2. //注意到曼哈顿距离下的圆为斜45度正方形,圆内点的个数即为答案
  3. //斜的正方形不好查询,考虑切比雪夫距离下的圆为平行于坐标轴的正方形 (相当于逆时针旋转45度)
  4. //把正方形角上的点以及更新的点曼哈顿距离下的坐标转成切比雪夫距离下的坐标
  5. //再在新正方形里二维前缀和即可
  6. #include<iostream>
  7. #include<cstdio>
  8. #include<algorithm>
  9. #include<cstring>
  10. #define maxn 1000000
  11. using namespace std;
  12. int n,m,tim,cnt,qcnt;
  13. int xx[maxn+5],yy[maxn+5];
  14. inline void change(int& x,int& y){//改变坐标系
  15. int xx=x,yy=y;
  16. x=xx+yy;
  17. y=xx-yy;
  18. }
  19. struct node{
  20. int a;
  21. int b;
  22. int c;
  23. int type;
  24. int val;
  25. int id;
  26. int ans;
  27. node(){
  28. }
  29. node(int _a,int _b,int _c,int _type){
  30. a=_a;
  31. b=_b;
  32. c=_c;
  33. type=_type;
  34. }
  35. node(int _a,int _b,int _c,int _type,int _val,int _id){
  36. a=_a;
  37. b=_b;
  38. c=_c;
  39. type=_type;
  40. val=_val;
  41. id=_id;
  42. ans=0;
  43. }
  44. }q[maxn+5];
  45. int cmpa(node p,node q){
  46. if(p.a==q.a){
  47. if(p.b==q.b) return p.c<q.c;
  48. else return p.b<q.b;
  49. }else return p.a<q.a;
  50. }
  51. int cmpb(node p,node q){
  52. if(p.b==q.b) return p.c<q.c;
  53. else return p.b<q.b;
  54. }
  55. struct fenwick_tree{
  56. int c[maxn+5];
  57. inline int lowbit(int x){
  58. return x&(-x);
  59. }
  60. inline void update(int pos,int val){
  61. for(int i=pos;i<=tim;i+=lowbit(i)) c[i]+=val;
  62. }
  63. inline int query(int pos){
  64. int ans=0;
  65. for(int i=pos;i>0;i-=lowbit(i)) ans+=c[i];
  66. return ans;
  67. }
  68. }T;
  69. node tmp[maxn+5];
  70. void cdq_divide(int l,int r){//orz cdq
  71. if(l==r) return;
  72. int mid=(l+r)>>1;
  73. cdq_divide(l,mid);
  74. cdq_divide(mid+1,r);
  75. int ptr=l-1;
  76. for(int i=mid+1;i<=r;i++){
  77. while(ptr<mid&&q[ptr+1].b<=q[i].b){
  78. ptr++;
  79. if(q[ptr].type==1) T.update(q[ptr].c,1);
  80. }
  81. if(q[i].type==2) q[i].ans+=T.query(q[i].c);
  82. }
  83. for(int i=l;i<=ptr;i++) if(q[i].type==1) T.update(q[i].c,-1);
  84. int num=l-1;
  85. int pl=l,pr=mid+1;
  86. while(pl<=mid&&pr<=r){
  87. if(cmpb(q[pl],q[pr])) tmp[++num]=q[pl++];
  88. else tmp[++num]=q[pr++];
  89. }
  90. while(pl<=mid) tmp[++num]=q[pl++];
  91. while(pr<=r) tmp[++num]=q[pr++];
  92. for(int i=l;i<=r;i++) q[i]=tmp[i];
  93. }
  94. char cmd[10];
  95. int ans[maxn+5];
  96. int main(){
  97. int p,k;
  98. scanf("%d %d",&n,&m);
  99. for(int i=1;i<=n;i++){
  100. xx[i]=i;
  101. scanf("%d",&yy[i]);
  102. tim++;
  103. q[++cnt]=node(xx[i]+yy[i],xx[i]-yy[i],tim,1);
  104. }
  105. for(int i=1;i<=m;i++){
  106. scanf("%s",cmd);
  107. if(cmd[0]=='M'){
  108. scanf("%d %d",&p,&k);
  109. tim++;
  110. yy[p]=k;
  111. q[++cnt]=node(xx[p]+yy[p],xx[p]-yy[p],tim,1);
  112. }else{
  113. int x1,y1,x2,y2;
  114. scanf("%d %d",&p,&k);
  115. x1=xx[p]-k;
  116. y1=yy[p];
  117. x2=xx[p]+k;
  118. y2=yy[p];
  119. change(x1,y1);
  120. change(x2,y2);
  121. tim++;
  122. qcnt++;
  123. q[++cnt]=node(x2,y2,tim,2,1,qcnt);
  124. q[++cnt]=node(x1-1,y2,tim,2,-1,qcnt);
  125. q[++cnt]=node(x2,y1-1,tim,2,-1,qcnt);
  126. q[++cnt]=node(x1-1,y1-1,tim,2,1,qcnt);
  127. }
  128. }
  129. sort(q+1,q+1+cnt,cmpa);
  130. cdq_divide(1,cnt);
  131. for(int i=1;i<=cnt;i++){
  132. if(q[i].type==2) ans[q[i].id]+=q[i].val*q[i].ans;
  133. }
  134. for(int i=1;i<=qcnt;i++) printf("%d\n",ans[i]);
  135. }

[BZOJ 2989]数列(CDQ 分治+曼哈顿距离与切比雪夫距离的转化)的更多相关文章

  1. [BZOJ 2989]数列(二进制分组+主席树)

    [BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ...

  2. [BZOJ 3456]城市规划(cdq分治+FFT)

    [BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...

  3. Bzoj 3170[Tjoi 2013]松鼠聚会 曼哈顿距离与切比雪夫距离

    3170: [Tjoi 2013]松鼠聚会 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1318  Solved: 664[Submit][Stat ...

  4. bzoj 4237 稻草人 - CDQ分治 - 单调栈

    题目传送门 传送点I 传送点II 题目大意 平面上有$n$个点.问存在多少个矩形使得只有左下角和右上角有点. 考虑枚举左下角这个点.然后看一下是个什么情况: 嗯对,是个单调栈.但不可能暴力去求每个点右 ...

  5. bzoj 3262 陌上花开 - CDQ分治 - 树状数组

    Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...

  6. BZOJ 2141: 排队 [CDQ分治]

    题意: 交换序列中两个元素,求逆序对 做分块做到这道题...一看不是三维偏序嘛.... 作为不会树套树的蒟蒻就写CDQ分治吧.... 对时间分治...x排序...y树状数组... 交换拆成两个插入两个 ...

  7. BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

    Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...

  8. BZOJ 2989: 数列/4170: 极光

    题解: n倍经验题 首先比较容易想到的是对绝对值分类讨论 然后是4维偏序 1.查询和修改顺序 2.x>y 3.a[x]>a[y] 4.(x+a[x])-(y+a[y])<=k 这样是 ...

  9. bzoj 4237: 稻草人 -- CDQ分治

    4237: 稻草人 Time Limit: 40 Sec  Memory Limit: 256 MB Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行 ...

随机推荐

  1. Django【第18篇】:Django之缓存

    Django 之缓存 一.缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存 ...

  2. Java课后作业04

    一.古罗马皇帝凯撒在打仗时曾经加密军事情报: 1.设计思想: 加密原理是abc等全部后移3位xyz分别等于abc,根据ascii码表的转化,将其利用charat()取单个字符进行转化,再利用Strin ...

  3. 为什么阿里巴巴要禁用Executors创建线程池?

    作者:何甜甜在吗 juejin.im/post/5dc41c165188257bad4d9e69 看阿里巴巴开发手册并发编程这块有一条:线程池不允许使用Executors去创建,而是通过ThreadP ...

  4. [BZOJ3527][ZJOI2014]力:FFT

    分析 整理得下式: \[E_i=\sum_{j<i}{\frac{q_i}{(i-j)^2}}-\sum_{j>i}{\frac{q_i}{(i-j)^2}}\] 假设\(n=5\),考虑 ...

  5. 使用OpenLayers 勾画地图

    <!DOCTYPE html> <html xmlns=http://www.w3.org/1999/xhtml> <head> <meta charset= ...

  6. 北风设计模式课程---单一职责原则(Single Responsibility Principle)

    北风设计模式课程---单一职责原则(Single Responsibility Principle) 一.总结 一句话总结: 一个类应该有且只有一个变化的原因:单一职责原则(SRP:Single Re ...

  7. windows下数据库备份bat

    @echo offset "Ymd=%date:~,4%%date:~5,2%%date:~8,2%"C:/mysql/bin/mysqldump --opt -u root -- ...

  8. chrome flash 自动暂停问题

    chrome flash 尺寸小于398*298时,只要宽和高某一个值小于对应值就会自动暂停,出现这个圆形的播放按钮.(估计是当广告处理了...) 将尺寸调大即可.

  9. gsensor方向调试【转】

    本文转载自:http://blog.csdn.net/guoguo295/article/details/19545089 版权声明:本文为博主原创文章,未经博主允许不得转载. 以下说明主要是针对gs ...

  10. Linux 用户必须知道的 14 个常用 Linux 终端快捷键

    简介:以下是一些每个 Linux 用户必须使用的键盘快捷键. 使用命令行时,这些 Linux 快捷键将提升你的工作效率和效率. 你知道什么把专业用户和普通用户分开的吗?掌握键盘快捷键. 好的!这虽不是 ...