【学习笔鸡】整体二分(P2617 Dynamic Rankings)

可以解决一些需要树套树才能解决的问题,但要求询问可以离线。

首先要找到一个具有可二分性的东西,比如区间\(k\)大,就很具有二分性。具体流程是这样的:

  • 假设当前分治是已知当前分治中的询问的范围是\([l,r]\),现在要进一步确定每个询问的范围。二分一个\(mid={l+r\over 2}\)出来,继续确定当前分治中心中每个询问的答案是大于还是小于\(mid\),若小于\(mid\)就放入左边递归,否则去右边递归。对于修改操作,我们同样地递归。注意对于修改拆分,将一个修改变为-1和+1。需要预处理每个修改前后的值是多少。
  • 撤回修改,继续递归

分析复杂度:

  • 对于分治操作,每次问题减半,那么就是\(T(n)=2T(\dfrac n 2)+F(n)\),\(F(n)\)是处理当前分治答案的时间复杂度。那么我们只要设计一个好的算法,使得可以在优秀的时间内处理当前层就可以行了。
  • 对于每个询问,每个询问被处理都是一条\(\log\)的链

时间复杂度看个人实现,好的实现可以做到\(O(\log n)\)的时间复杂度

建议写的时候和写线段树的递归方法统一。 不知道为啥我这份代码写得这么快,Hong Kong journalist

  1. //@winlere
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<vector>
  6. using namespace std; typedef long long ll;
  7. inline int qr(){
  8. register int ret=0,f=0;
  9. register char c=getchar();
  10. while(c<48||c>57)f|=c==45,c=getchar();
  11. while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
  12. return f?-ret:ret;
  13. }
  14. const int maxn=1e5+5;
  15. int sav[maxn<<1],len,n,m,cnt,data[maxn],seg[maxn],ans[maxn];
  16. inline void add(const int&pos,const int&tag){for(int t=pos;t<=len&&t>0;t+=t&-t) seg[t]+=tag;}
  17. inline int que(const int&pos){ int ret=0; for(int t=pos;t>0;t-=t&-t) ret+=seg[t]; return ret; }
  18. struct DATA{int ty,l,r,k; DATA(){ty=l=r=k=0;} DATA(int a,int b,int c,int d){ty=a;l=b;r=c;k=d;}};
  19. vector<DATA> q;
  20. inline void addc(const int&pos,const int&tag){
  21. q.push_back(DATA(0,data[pos],-1,pos));
  22. q.push_back(DATA(0,tag,1,pos));
  23. data[pos]=tag; sav[++cnt]=tag;
  24. }
  25. void divd(const int&l,const int&r,vector<DATA>&ve){
  26. if(l==r||ve.empty()) {for(const auto&t:ve) ans[t.ty]=l; return;}
  27. vector<DATA> lef,rgt;
  28. int mid=(l+r)>>1,temp;
  29. for(auto&t:ve)
  30. if(!t.ty)
  31. if(t.l<=mid) add(t.k,t.r),lef.push_back(t);
  32. else rgt.push_back(t);
  33. else
  34. if((temp=que(t.r)-que(t.l-1))>=t.k) lef.push_back(t);
  35. else t.k-=temp,rgt.push_back(t);
  36. for(auto&t:lef) if(!t.ty) add(t.k,-t.r);
  37. divd(l,mid,lef); divd(mid+1,r,rgt);
  38. }
  39. int main(){
  40. n=qr(); m=qr();
  41. memset(data,-1,sizeof data);
  42. for(int t=1;t<=n;++t) q.push_back(DATA(0,sav[++cnt]=data[t]=qr(),1,t));
  43. for(int t=1,t1,t2,t3;t<=m;++t) {
  44. static char c[20];
  45. scanf("%s",c+1);
  46. if(c[1]=='C') t1=qr(),t2=qr(),addc(t1,t2);
  47. if(c[1]=='Q') t1=qr(),t2=qr(),t3=qr(),q.push_back(DATA(t,t1,t2,t3));
  48. }
  49. sort(sav+1,sav+cnt+1);
  50. len=unique(sav+1,sav+cnt+1)-sav-1;
  51. for(auto&t:q)
  52. if(!t.ty)
  53. t.l=lower_bound(sav+1,sav+len+1,t.l)-sav;
  54. divd(1,len,q);
  55. for(int t=1;t<=m;++t) if(ans[t]) printf("%d\n",sav[ans[t]]);
  56. return 0;
  57. }

【学习笔鸡】整体二分(P2617 Dynamic Rankings)的更多相关文章

  1. 2018.07.01洛谷P2617 Dynamic Rankings(带修主席树)

    P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...

  2. 洛谷P2617 Dynamic Rankings (主席树)

    洛谷P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a ...

  3. 洛谷 P2617 Dynamic Rankings 解题报告

    P2617 Dynamic Rankings 题目描述 给定一个含有\(n\)个数的序列\(a[1],a[2],a[3],\dots,a[n]\),程序必须回答这样的询问:对于给定的\(i,j,k\) ...

  4. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

  5. 【学习笔鸡】快速沃尔什变换FWT

    [学习笔鸡]快速沃尔什变换FWT OR的FWT 快速解决: \[ C[i]=\sum_{j|k=i} A[j]B[k] \] FWT使得我们 \[ FWT(C)=FWT(A)*FWT(B) \] 其中 ...

  6. Luogu P2617 Dynamic Rankings(整体二分)

    题目 动态区间第K小模板题. 一个非常可行的办法是BIT套动态开点权值SegTree,但是它跑的实在太慢了. 然后由于这题并没有强制在线,所以我们可以使用整体二分来吊打树套树. 当然如果强制在线的话就 ...

  7. 洛谷$P2617\ Dynamic\ Rankings$ 整体二分

    正解:整体二分 解题报告: 传送门$w$ 阿查询带修区间第$k$小不显然整体二分板子呗,,, 就考虑先按时间戳排序(,,,其实并不需要读入的时候就按着时间戳排的鸭$QwQ$ 每次二分出$mid$先把所 ...

  8. 洛谷P2617 Dynamic Rankings

    带修主席树模板题 主席树的单点修改就是把前缀和(大概)的形式改成用树状数组维护,每个树状数组的元素都套了一个主席树(相当于每个数组的元素root[i]都是主席树,且这个主席树维护了(i - lowbi ...

  9. P2617 Dynamic Rankings

    题目描述 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤ ...

随机推荐

  1. NSDate 格式化含有毫秒

    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"]; 版权声明:本文为博主原创文章,未经博主允许不得转载.

  2. supersocket新的配置属性 "textEncoding"

    在 SuperSocket 1.6 之前的版本, 当你通过Session对象发送文本时, 将文本信息转换成能够通过Socket传输的二进制数据的默认编码是UTF8. 你可以通过设置 Session 的 ...

  3. Python--day20--模块的导入

    1,模块的导入步骤: 2,,给文件起别名的用处: 重命名之后,原来的名字就不能用了 3,虽然这样写可以,但是不推荐,代码可读性不强,以后代码的修改成本也增加: 4,模块的导入顺序: 5,导入变量名的两 ...

  4. 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...

  5. yii框架不输出头文件和尾文件

    控制器: public function actionCat(){ return $this->renderPartial('cat');} 在进行页面输出渲染的时候. 1.render 输出父 ...

  6. java.lang.ClassCastException: com.sun.proxy.$Proxy6 cannot be cast to com.etc.service.serviceImpl.BankServiceImpl

    错误原因: java.lang.ClassCastException: com.sun.proxy.$Proxy6 cannot be cast to com.etc.service.serviceI ...

  7. Python--day46--MySQL视图

    1,创建一个视图(给临时表起一个别名v1),视图也虚拟出来的,并非真正的物理表,不能直接往里面插数据.它的数据是动态的读出来的. create view v1 as select * from use ...

  8. H5 存储数据sessionStorage

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. linux 共享队列

    一个设备驱动, 在许多情况下, 不需要它自己的工作队列. 如果你只偶尔提交任务给队列, 简单地使用内核提供的共享的, 缺省的队列可能更有效. 如果你使用这个队列, 但是, 你 必须明白你将和别的在共享 ...

  10. linux Tasklet 实现

    记住 tasklet 是一个特殊的函数, 可能被调度来运行, 在软中断上下文, 在一个系统决 定的安全时间中. 它们可能被调度运行多次, 但是 tasklet 调度不累积; ; tasklet 只 运 ...