显然是块状链表的经典题。但是经典做法的复杂度是O(n*sqrt(n)*log^2(n))的,出题人明确说了会卡掉。

于是我们考虑每个块内记录前n个块的权值分块。

查询的时候差分什么的,复杂度就是O(n*sqrt(n))的了。

插入的时候为了防止块过大,要考虑裂块(细节较多)。

感谢bzoj提供O2,我的STL块链才能通过(list+vector)。

  1. #include<cstdio>
  2. #include<list>
  3. #include<vector>
  4. #include<cmath>
  5. #include<algorithm>
  6. using namespace std;
  7. #define X first
  8. #define Y second
  9. int num[70001],l[270],Limit,ans,n,tmp[35001],x,y,val,m;
  10. char op[1];
  11. struct VAL_BLOCK
  12. {
  13. int b[70001],sumv[270];
  14. void insert(const int &x){++b[x]; ++sumv[num[x]];}
  15. void erase(const int &x){--b[x]; --sumv[num[x]];}
  16. }S;
  17. struct BLOCK
  18. {
  19. vector<int>v;
  20. VAL_BLOCK T;
  21. BLOCK(){}
  22. };
  23. list<BLOCK>List;
  24. typedef list<BLOCK>::iterator LER;
  25. typedef vector<int>::iterator VER;
  26. typedef pair<LER,VER> Pair;
  27. Pair Find(const int &p)
  28. {
  29. int cnt=0; LER i=List.begin();
  30. for(;i!=List.end();++i)
  31. {
  32. cnt+=(*i).v.size();
  33. if(cnt>=p)
  34. {
  35. cnt-=(*i).v.size();
  36. for(VER j=(*i).v.begin();j!=(*i).v.end();++j)
  37. if((++cnt)==p)
  38. return make_pair(i,j);
  39. }
  40. }
  41. --i; return make_pair(i,(*i).v.end());
  42. }
  43. void Insert(const int &p,const int &V)
  44. {
  45. Pair Bel=Find(p);
  46. (*Bel.X).v.insert(Bel.Y,V);
  47. for(LER i=Bel.X;i!=List.end();++i)
  48. (*i).T.insert(V);
  49. if((*Bel.X).v.size()>Limit)
  50. {
  51. LER Near=Bel.X; ++Near;
  52. int Last=(*Bel.X).v.back();
  53. if((*Near).v.size()>Limit || Near==List.end())
  54. {
  55. Near=List.insert(Near,BLOCK());
  56. (*Near).T=(*Bel.X).T;
  57. }
  58. (*Near).v.insert((*Near).v.begin(),Last);
  59. (*Bel.X).T.erase(Last);
  60. (*Bel.X).v.pop_back();
  61. }
  62. }
  63. void Update(const int &p,const int &V)
  64. {
  65. Pair Bel=Find(p);
  66. for(LER i=Bel.X;i!=List.end();++i)
  67. (*i).T.erase(*Bel.Y),
  68. (*i).T.insert(V);
  69. (*Bel.Y)=V;
  70. }
  71. int Kth(const int &L,const int &R,const int &K)
  72. {
  73. Pair P1=Find(L),P2=Find(R);
  74. int cnt=0,res;
  75. if(P1.X==P2.X)
  76. {
  77. for(VER i=P1.Y;i<=P2.Y;++i) S.insert(*i);
  78. for(int i=1;;++i)
  79. {
  80. cnt+=S.sumv[i];
  81. if(cnt>=K)
  82. {
  83. cnt-=S.sumv[i];
  84. for(int j=l[i];;++j)
  85. {
  86. cnt+=S.b[j];
  87. if(cnt>=K) {res=j; goto OUT2;}
  88. }
  89. }
  90. } OUT2:
  91. for(VER i=P1.Y;i<=P2.Y;++i) S.erase(*i);
  92. return res;
  93. }
  94. for(VER i=P1.Y;i!=(*P1.X).v.end();++i) S.insert(*i);
  95. for(VER i=(*P2.X).v.begin();i<=P2.Y;++i) S.insert(*i);
  96. LER LB=P1.X,RB=P2.X; --RB;
  97. for(int i=1;;++i)
  98. {
  99. cnt+=((*RB).T.sumv[i]-(*LB).T.sumv[i]+S.sumv[i]);
  100. if(cnt>=K)
  101. {
  102. cnt-=((*RB).T.sumv[i]-(*LB).T.sumv[i]+S.sumv[i]);
  103. for(int j=l[i];;++j)
  104. {
  105. cnt+=((*RB).T.b[j]-(*LB).T.b[j]+S.b[j]);
  106. if(cnt>=K) {res=j; goto OUT;}
  107. }
  108. }
  109. } OUT:
  110. for(VER i=P1.Y;i!=(*P1.X).v.end();++i) S.erase(*i);
  111. for(VER i=(*P2.X).v.begin();i<=P2.Y;++i) S.erase(*i);
  112. return res;
  113. }
  114. void Val_Makeblock()
  115. {
  116. int tot=1,sz=sqrt(70000); if(!sz) sz=1;
  117. for(;tot*sz<=70000;++tot)
  118. {
  119. l[tot]=(tot-1)*sz;
  120. int R=tot*sz-1;
  121. for(int i=l[tot];i<=R;++i) num[i]=tot;
  122. }
  123. l[tot]=(tot-1)*sz;
  124. for(int i=l[tot];i<=70000;++i) num[i]=tot;
  125. }
  126. void Makeblock()
  127. {
  128. int sz=sqrt(n),tot=1; if(!sz) sz=1;
  129. Limit=sqrt(n+35000);
  130. for(;tot*sz<n;++tot)
  131. {
  132. LER End=List.insert(List.end(),BLOCK());
  133. (*End).v.assign(tmp+(tot-1)*sz+1,tmp+tot*sz+1);
  134. }
  135. LER End=List.insert(List.end(),BLOCK());
  136. (*End).v.assign(tmp+(tot-1)*sz+1,tmp+n+1);
  137. }
  138. void Init_Ts()
  139. {
  140. LER i=List.begin();
  141. for(VER j=(*i).v.begin();j!=(*i).v.end();++j)
  142. (*i).T.insert(*j);
  143. ++i;
  144. for(LER Front=List.begin();i!=List.end();++i,++Front)
  145. {
  146. (*i).T=(*Front).T;
  147. for(VER j=(*i).v.begin();j!=(*i).v.end();++j)
  148. (*i).T.insert(*j);
  149. }
  150. }
  151. int main()
  152. {
  153. scanf("%d",&n);
  154. for(int i=1;i<=n;++i) scanf("%d",&tmp[i]);
  155. Makeblock();
  156. Val_Makeblock();
  157. Init_Ts();
  158. scanf("%d",&m);
  159. for(;m;--m)
  160. {
  161. scanf("%s%d",op,&x); x^=ans;
  162. if(op[0]=='Q')
  163. {
  164. scanf("%d%d",&y,&val); y^=ans; val^=ans;
  165. printf("%d\n",ans=Kth(x,y,val));
  166. }
  167. else if(op[0]=='M')
  168. {
  169. scanf("%d",&val); val^=ans;
  170. Update(x,val);
  171. }
  172. else
  173. {
  174. scanf("%d",&val); val^=ans;
  175. Insert(x,val);
  176. }
  177. }
  178. return 0;
  179. }

【函数式权值分块】【块状链表】bzoj3065 带插入区间K小值的更多相关文章

  1. [BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树

    刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录. Portal Gun:[BZOJ3065]带插入区间k小值 ...

  2. BZOJ3065 带插入区间K小值 || 洛谷P4278

    这是一道让我崩溃的题...... 然鹅洛谷上时限被改然后只有20分......好像所有人都被卡了(雾) 由于替罪羊树不是依靠旋转操作而是依靠暴力重构的方式维护树的平衡,所以我们可以考虑使用替罪羊树套区 ...

  3. bzoj3065: 带插入区间K小值

    无聊来写了下 一开始发现树高是O(n)的,然后就MLE了,进去看了下发现没有重构! 看了半天发现调用错了函数 然后进去又发现不满足sz = ch[0]->sz + ch[1]->sz + ...

  4. 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树

    [BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...

  5. 3065: 带插入区间K小值_树套树_替罪羊树_权值线段树

    经过周六一天,周一3个小时的晚自习,周二2个小时的疯狂debug,终于凭借自己切掉了这道树套树题. Code: #include <cstdio> #include <algorit ...

  6. bzoj 3065: 带插入区间K小值 替罪羊树 && AC300

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 1062  Solved: 253[Submit][Status] Des ...

  7. BZOJ 3065 带插入区间K小值(sag套线段树)

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 4696  Solved: 1527[Submit][Status][Di ...

  8. 【学习笔记】浅析平衡树套线段树 & 带插入区间K小值

    常见的树套树 一般来说,在嵌套数据结构中,线段树多被作为外层结构使用. 但线段树毕竟是 静态 的结构,导致了一些不便. 下面是一个难以维护的例子: 带插入区间 \(k\) 小值问题 来源:Luogu ...

  9. 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树

    题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...

随机推荐

  1. json获取属性值的方式

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript(Standard ECMA-262 ...

  2. Bash 实例,第一部分

    您可能要问:为什么要学习 Bash 编程?好,以下是几条令人信服的理由: 已经在运行它 如果查看一下,可能会发现:您现在正在运行 bash.因为 bash 是标准 Linux shell,并用于各种目 ...

  3. 计算1-1/x+1/x*x

    // algo1-1.cpp 计算1-1/x+1/x*x. #include<stdio.h> #include<sys/timeb.h> void main() { time ...

  4. 【BZOJ2227】【ZJOI2011】看电影 [组合数][质因数分解]

    看电影 Time Limit: 10 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 到了难得的假期,小白班上组织大家去看 ...

  5. [BZOJ1984]月下“毛景树”解题报告|树链剖分

    Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树” ...

  6. 路径方案数_mod_SPFA_记忆化搜索_C++

    本文含有原创题,涉及版权利益问题,严禁转载,违者追究法律责任 本来是写个 DP 分分钟就 A 了,结果老师要我们写记忆化搜索(无奈脸) 算啦,随手一改又是一个标准的记忆化搜索(目测好像是记忆化搜索容易 ...

  7. 【反演复习计划】【bzoj1011】zap-queries

    快三个月没做反演题了吧…… 感觉高一上学期学的全忘了…… 所以还得从零开始学推式子. # bzoj1011 标签(空格分隔): 未分类 --- 原题意思是求以下式子:$Ans=\sum\limits_ ...

  8. centos 自启动

    https://blog.phpha.com/backup/archives/1458.html 1.服务 chkconfig 服务名 on 查看所有可以 chkconfig --list 2 修改 ...

  9. 多个springboot项目部署在同一tomcat上,出现jmx错误

    多个springboot项目部署在同一tomcat上,出现jmx错误 原因:因为jmx某些东西重复,禁用jmx就可以了 endpoints.jmx.unique-names=true

  10. Java中的new关键字和引用传参

    先看看Java中如何使用new关键字创建一个对象的. [java] view plain copy public class Student { public String name; public  ...