欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1901


题意概括

  给你一段序列(n个数),让你支持一些操作(共m次),

  有两种操作,一种是询问区间第k小,一种是单点修改。

  n,m<=10000


题解

  这个主席树的写法是我自己造出来的。

  主席树的查询区间第k大需要依赖前缀和。

  树状数组最擅长这个了,就让他来干。

  原理是这样的:

  先离散化,包括修改操作里面的数字也要离散化。

  然后建树,包括修改操作所涉及的数值也要建。

  现在总共有n个线段树。

  第0棵树是最完整的,故我们把这棵树的每一个节点都当作一个树状数组的起点,即该树状数组的第一项。

  然后往下一棵树走,当然下一棵树不一定有这个节点,那么不停的走下去,这个可以在建树的时候预先处理一个Next数组来优化。

  走到下一个这个位置的节点之后,我们再把这个节点作为该树状数组的第二项。

  这样我们有大约n*4(第0棵树的节点个数)个树状数组了。

  然而不处理要超空间。

  所以有两种方案,一种是vector,一种是把所有的树状数组连起来,变成一个大的。

  然而查询之类的就和普通的主席树差不多了。

细节上要大大的注意!


代码

  1. #include <cstring>
  2. #include <algorithm>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <cmath>
  6. #include <vector>
  7. using namespace std;
  8. const int N=10005,S=N*2*20*4;//v=4*node=4*20*hs=4*20*2*n
  9. struct Que{
  10. char op;
  11. int a,b,c;
  12. void read(){
  13. char opc[5];
  14. scanf("%s%d%d",opc,&a,&b);
  15. op=opc[0];
  16. if (op=='Q')
  17. scanf("%d",&c);
  18. }
  19. }q[N];
  20. vector <int> vec[N];
  21. int n,m,v[N],Ha[N*2],hs=0,total=0,totarr=0;
  22. int root[N],ls[S],rs[S],sum[S],pos[S],Next[S],p[S];
  23. void LSH(){
  24. int hs_=1;
  25. sort(Ha+1,Ha+hs+1);
  26. for (int i=2;i<=hs;i++)
  27. if (Ha[i]!=Ha[i-1])
  28. Ha[++hs_]=Ha[i];
  29. hs=hs_;
  30. }
  31. int find(int x){
  32. int L=1,R=hs,mid;
  33. while (L<=R){
  34. mid=(L+R)>>1;
  35. if (Ha[mid]==x)
  36. return mid;
  37. if (Ha[mid]<x)
  38. L=mid+1;
  39. else
  40. R=mid-1;
  41. }
  42. exit(233);
  43. }
  44. int build(int L,int R){
  45. int rt=++total;
  46. if (L==R){
  47. ls[rt]=rs[rt]=0;
  48. return rt;
  49. }
  50. int mid=(L+R)>>1;
  51. ls[rt]=build(L,mid);
  52. rs[rt]=build(mid+1,R);
  53. return rt;
  54. }
  55. int lowbit(int x){
  56. return x&-x;
  57. }
  58. void add(int x,int v){
  59. for (;x<=totarr;x+=lowbit(x))
  60. sum[x]+=v;
  61. }
  62. int Sum(int x){
  63. int ans=0;
  64. for (;x>0;x-=lowbit(x))
  65. ans+=sum[x];
  66. return ans;
  67. }
  68. void add_tree(int prt,int &rt,int L,int R,int pos){
  69. if (!rt||rt==prt)
  70. rt=++total;
  71. Next[prt]=rt;
  72. if (L==R)
  73. return;
  74. int mid=(L+R)>>1;
  75. if (pos<=mid){
  76. add_tree(ls[prt],ls[rt],L,mid,pos);
  77. if (!rs[rt])
  78. rs[rt]=rs[prt];
  79. }
  80. else {
  81. add_tree(rs[prt],rs[rt],mid+1,R,pos);
  82. if (!ls[rt])
  83. ls[rt]=ls[prt];
  84. }
  85. }
  86. void build_treearr(int srt,int L,int R){
  87. for (int i=srt;i;i=Next[i])
  88. p[i]=++totarr;
  89. if (L==R)
  90. return;
  91. int mid=(L+R)>>1;
  92. build_treearr(ls[srt],L,mid);
  93. build_treearr(rs[srt],mid+1,R);
  94. }
  95. void update(int rt,int L,int R,int pos,int v){
  96. add(p[rt],v);
  97. if (L==R)
  98. return;
  99. int mid=(L+R)>>1;
  100. if (pos<=mid)
  101. update(ls[rt],L,mid,pos,v);
  102. else
  103. update(rs[rt],mid+1,R,pos,v);
  104. }
  105. int query(int prt,int rt,int L,int R,int k){
  106. if (L==R)
  107. return Ha[L];
  108. int mid=(L+R)>>1;
  109. int LV=Sum(p[ls[rt]])-Sum(p[ls[prt]]);
  110. if (k<=LV)
  111. return query(ls[prt],ls[rt],L,mid,k);
  112. else
  113. return query(rs[prt],rs[rt],mid+1,R,k-LV);
  114. }
  115. int main(){
  116. scanf("%d%d",&n,&m);
  117. for (int i=1;i<=n;i++)
  118. scanf("%d",&v[i]),Ha[++hs]=v[i];
  119. for (int i=1;i<=m;i++){
  120. q[i].read();
  121. if (q[i].op=='C')
  122. Ha[++hs]=q[i].b;
  123. }
  124. LSH();
  125. for (int i=1;i<=n;i++)
  126. vec[i].clear();
  127. for (int i=1;i<=n;i++)
  128. vec[i].push_back(v[i]);
  129. for (int i=1;i<=m;i++)
  130. if (q[i].op=='C')
  131. vec[q[i].a].push_back(q[i].b);
  132. memset(sum,0,sizeof sum);
  133. memset(pos,0,sizeof pos);
  134. memset(Next,0,sizeof Next);
  135. memset(root,0,sizeof root);
  136. root[0]=build(1,hs);
  137. for (int i=1;i<=n;i++)
  138. for (int j=0;j<vec[i].size();j++)
  139. add_tree(root[i-1],root[i],1,hs,find(vec[i][j]));
  140. build_treearr(root[0],1,hs);
  141. for (int i=1;i<=n;i++)
  142. update(root[i],1,hs,find(v[i]),1);
  143. for (int i=1;i<=m;i++)
  144. if (q[i].op=='C'){
  145. update(root[q[i].a],1,hs,find(v[q[i].a]),-1);
  146. update(root[q[i].a],1,hs,find(v[q[i].a]=q[i].b),1);
  147. }
  148. else
  149. printf("%d\n",query(root[q[i].a-1],root[q[i].b],1,hs,q[i].c));
  150. return 0;
  151. }

  

BZOJ1901 Zju2112 Dynamic Rankings 主席树的更多相关文章

  1. 【BZOJ1901】Zju2112 Dynamic Rankings 主席树+树状数组

    [BZOJ1901]Zju2112 Dynamic Rankings Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j ...

  2. Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6321  Solved: 2628[Su ...

  3. bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB Description 给定一个含有n个数的序列a[1] ...

  4. [luogu2617][bzoj1901][Zju2112]Dynamic Rankings【树套树+树状数组+主席树】

    题目网址 [传送门] 题目大意 请你设计一个数据结构,支持单点修改,区间查询排名k. 感想(以下省略脏话inf个字) 真的强力吹爆洛谷数据,一般的树套树还给我T了一般的点,加强的待修主席树还给我卡了几 ...

  5. BZOJ1901 Zju2112 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≤j- ...

  6. [bzoj1901][Zju2112]Dynamic Rankings_主席树

    Dynamic Rankings bzoj-1901 Zju-2112 题目大意:给定一个n个数的序列,m个操作,支持:单点修改:查询区间k小值. 注释:$1\le n,m\le 10^4$. 想法: ...

  7. [BZOJ1901]Zju2112 Dynamic Rankings

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

  8. BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB Submit: 6058 Solved: 2521 [Su ...

  9. bzoj1901: Zju2112 Dynamic Rankings(BIT套主席树)

    带修改的题主席树不记录前缀,只记录单点,用BIT统计前缀.  对于BIT上每一个点建一棵主席树,修改和询问的时候用BIT跑,在主席树上做就行了.  3k4人AC的题#256...应该不算慢 #incl ...

随机推荐

  1. Spring XML配置里的Bean自动装配

    Spring自动装配 这段是我们之前编写的代码,代码中我们使用了P命名空间 并且使用手动装配的方式将car <bean id="address" class="cn ...

  2. asp.net mvc url应用

    //url加密与解密string res1 = HttpUtility.UrlEncode("7Z2K5Lgk/iI="); //值是7Z2K5Lgk%2fiI%3d string ...

  3. IO流总结笔记一

    ​ IO流继承关系图 IO概述 IO流是用来处理设备上数据的输入输出. 具体设备有:硬盘,内存,键盘录入等等. IO流的具体分类: 1,根据处理的数据类型不同分为:字节流和字符流,字节流读取的最小单位 ...

  4. Spring+CXF整合来管理webservice(服务器启动发布webservice)

    Spring+CXF整合来管理webservice    实现步骤:      1. 添加cxf.jar 包(集成了Spring.jar.servlet.jar ),spring.jar包 ,serv ...

  5. TrimLeft TrimRight

    strming.TrimLeft();  //将字符串最前面的空格修整掉.当在没有参数的情况下调用时,TrimLeft删除换行符,空格和tab字符. strming.TrimRight()://消除从 ...

  6. Django配置富文本编辑器kindeditor

    一.简介 django是一个容易快速上手的web框架,用它来创建内容驱动型的网站(比如独立博客)十分方便.遗憾的是,django并没有提供官方的富文本编辑器,而后者恰好是内容型网站后台管理中不可或缺的 ...

  7. MR运动静止用户区分

    1.客户端打开菜单[MR]-[MR室内室外判定设置] 设置主小区是室外站且主小区信号比较强时RSRP门限 2.设置"上报数据用户临小区切换次数门限设置"值为15 mysql中t_m ...

  8. python根据服务名获取服务启动路径

    #coding=utf8 import _winreg as winreg class Win32Environment: """Utility class to get ...

  9. git 使用https 和SSH 提交远程库小总结

    一.使用https提交远程库 首先已经git commit -m “注释” 本地仓库关联远程github服务器:git remote add origin  “https://XXXX.git” 提交 ...

  10. Android通讯:通话

    Android通讯之通话功能的实现: 在Android中,android.telephony.TelephonyManager对象是开发者获取当前通话网络相关信息的窗口,通过TelephonyMana ...