题意:

一开始有n个非负整数h[i],接下来会进行m次操作,第i次会给出一个数c[i],要求选出c[i]个大于0的数并将它们-1,问最多可以进行多少次?

分析:

首先一个显然的贪心就是每次都将最大的c[i]个数-1,于是就可以用无旋式treap来维护,基本操作中split_k和split_v都使用普通的merge,但在提取区间并打完标记后,因为整个序列的单调性发生改变,需要使用启发式合并(只在修改过后使用)。

code

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<string>
  6. #include<algorithm>
  7. #include<cmath>
  8. #include<vector>
  9. #include<ctime>
  10. #include<queue>
  11. using namespace std;
  12. template<typename T>
  13. inline void read(T &x) {
  14. T i = 0, f = 1;
  15. char ch = getchar();
  16. for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
  17. if(ch == '-') f = -1, ch = getchar();
  18. for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
  19. x = i * f;
  20. }
  21. template<typename T>
  22. inline void wr(T x) {
  23. if(x < 0) putchar('-'), x = -x;
  24. if(x > 9) wr(x / 10);
  25. putchar(x % 10 + '0');
  26. }
  27. const int N = 1e6 + 50, OO = 0x3f3f3f3f;
  28. int n, m, h[N], c[N];
  29. inline int Rand(){
  30. static int RAND_VAL = 1388593021;
  31. return RAND_VAL += RAND_VAL << 2 | 1;
  32. }
  33. #define SZ(x) (x?x->sze:0)
  34. #define V(x) (x?x->val:OO)
  35. struct node{
  36. node *lc, *rc;
  37. int sze, pri, val, tag;
  38. node():lc(NULL), rc(NULL){}
  39. inline void add(int v){
  40. val += v, tag += v;
  41. }
  42. inline void pushDown(){
  43. if(tag != 0){
  44. if(lc) lc->add(tag);
  45. if(rc) rc->add(tag);
  46. tag = 0;
  47. }
  48. }
  49. inline node* upt(){
  50. sze = SZ(lc) + SZ(rc) + 1;
  51. return this;
  52. }
  53. inline void print(){
  54. pushDown();
  55. if(lc) lc->print();
  56. cout<< val<<" ";
  57. if(rc) rc->print();
  58. }
  59. }pool[N], *tail = pool, *rt = NULL;
  60. inline node* newNode(int v){
  61. node *x = tail++;
  62. x->val = v;
  63. x->lc = x->rc = NULL;
  64. x->pri = Rand();
  65. x->tag = 0;
  66. x->sze = 1;
  67. return x;
  68. }
  69. inline node* Merge_o(node *x, node *y){
  70. if(!x) return y;
  71. if(!y) return x;
  72. node *L, *R;
  73. if(x->pri < y->pri){
  74. x->pushDown();
  75. x->rc = Merge_o(x->rc, y);
  76. return x->upt();
  77. }
  78. else {
  79. y->pushDown();
  80. y->lc = Merge_o(x, y->lc);
  81. return y->upt();
  82. }
  83. }
  84. inline void Split_v(node *x, int v, node *&L, node *&R);
  85. inline node* Merge(node *x, node *y){
  86. if(!x) return y;
  87. if(!y) return x;
  88. x->pushDown(), y->pushDown();
  89. if(x->pri > y->pri) swap(x, y);
  90. node *L, *R;
  91. Split_v(y, x->val, L, R);
  92. x->lc = Merge(x->lc, L);
  93. x->rc = Merge(x->rc, R);
  94. x->upt();
  95. return x;
  96. }
  97. inline void Split_k(node *x, int k, node *&L, node *&R){
  98. if(x == NULL){L = NULL, R = NULL; return;}
  99. x->pushDown();
  100. if(SZ(x->lc) < k){
  101. Split_k(x->rc, k - SZ(x->lc) - 1, L, R);
  102. x->rc = NULL; x->upt();
  103. L = Merge_o(x, L);
  104. }
  105. else{
  106. Split_k(x->lc, k, L, R);
  107. x->lc = NULL; x->upt();
  108. R = Merge_o(R, x);
  109. }
  110. }
  111. inline void Split_v(node *x, int v, node *&L, node *&R){
  112. if(x == NULL){L = NULL, R = NULL; return;}
  113. x->pushDown();
  114. if(V(x) <= v){
  115. Split_v(x->rc, v, L, R);
  116. x->rc = NULL; x->upt();
  117. L = Merge_o(x, L);
  118. }
  119. else{
  120. Split_v(x->lc, v, L, R);
  121. x->lc = NULL, x->upt();
  122. R = Merge_o(R, x);
  123. }
  124. }
  125. inline node* build(){
  126. static node* stk[N];
  127. node* pre;
  128. int top = 0;
  129. for(register int i = 1; i <= n; i++){
  130. node *x = newNode(h[i]);
  131. pre = NULL;
  132. while(top && stk[top]->pri > x->pri)
  133. pre = stk[top]->upt(), stk[top--] = NULL;
  134. if(stk[top]) stk[top]->rc = x;
  135. x->lc = pre; stk[++top] = x;
  136. }
  137. while(top) stk[top--]->upt();
  138. return stk[1];
  139. }
  140. int main(){
  141. freopen("h.in", "r", stdin);
  142. read(n), read(m);
  143. for(register int i = 1; i <= n; i++) read(h[i]);
  144. for(register int i = 1; i <= m; i++) read(c[i]);
  145. sort(h + 1, h + n + 1);
  146. rt = build();
  147. for(register int i = 1; i <= m; i++){
  148. if(!c[i]) continue;
  149. if(c[i] > n){
  150. wr(i - 1);
  151. return 0;
  152. }
  153. node *L, *R, *p, *q;
  154. Split_v(rt, 0, L, R);
  155. if(SZ(R) >= c[i]){
  156. Split_k(R, SZ(R) - c[i], p, q);
  157. if(q) q->add(-1);
  158. R = Merge(p, q);
  159. }
  160. else{
  161. wr(i - 1);
  162. return 0;
  163. }
  164. rt = Merge(L, R);
  165. }
  166. wr(m);
  167. return 0;
  168. }

NOIP 模拟 序列操作 - 无旋treap的更多相关文章

  1. 【算法学习】Fhq-Treap(无旋Treap)

    Treap——大名鼎鼎的随机二叉查找树,以优异的性能和简单的实现在OIer们中广泛流传. 这篇blog介绍一种不需要旋转操作来维护的Treap,即无旋Treap,也称Fhq-Treap. 它的巧妙之处 ...

  2. 【序列操作V】平衡树(无旋treap)

    题目描述 维护一个队列,初始为空.依次加入 n(1≤n≤105)个数 ai(-109≤ai≤109),第 i(1≤i≤n)个数加入到当前序列第 bi(0≤bi≤当前序列长度)个数后面.输出最终队列. ...

  3. 无旋treap的区间操作实现

    最近真的不爽...一道维修数列就做了我1上午+下午1h+1晚上+晚上1h+上午2h... 一道不错的自虐题... 由于这一片主要讲思想,代码我放这里了 不会无旋treap的童鞋可以进这里 呵呵... ...

  4. [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec  Mem ...

  5. [BZOJ3223]文艺平衡树 无旋Treap

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Description 您需要写一种数据结构(可参考题目标题),来维护一个 ...

  6. [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 ...

  7. 无旋treap大法好

    无旋Treap大法好 原理? 是一棵二叉查找树: 一个节点左子树权值都比他小,右子树权值都比他大 所以可以维护序列(以位置为权值),或数值(以数值为权值) 是一个堆: 每个节点除了上述提到的权值外,还 ...

  8. 模板 - 数据结构 - 可持久化无旋Treap/PersistentFHQTreap

    有可能当树中有键值相同的节点时,貌似是要对Split和Merge均进行复制的,本人实测:只在Split的时候复制得到了一个WA,但只在Merge的时候复制还是AC,可能是恰好又躲过去了.有人说假如确保 ...

  9. BZOJ3678 wangxz与OJ (平衡树 无旋treap)

    题面 维护一个序列,支持以下操作: 1.在某个位置插入一段值连续的数. 2.删除在当前序列位置连续的一段数. 3.查询某个位置的数是多少. 题解 显然平衡树,一个点维护一段值连续的数,如果插入或者删除 ...

随机推荐

  1. .net core 分布式性能计数器的实现

    1.特别鸣谢张善友老师的指点; 2.分布式性能计数器链接地址:https://mp.weixin.qq.com/s/hPV_bNZD4XmjP0QTE54pWA

  2. 学习笔记(四):jQuery之动画效果

    1.show()显示效果 语法:show(speed,callback) Number/String,Function speend为动画执行时间,单位为毫秒.也可以为slow"," ...

  3. The Swift Programming Language 中文翻译版

    原文(http://www.cnblogs.com/lkvt/p/3765349.html) 一.Welcome to Swift 1.关于Swift Swift是一种用于iOS和OS X应用的全新编 ...

  4. Altium Designer中画pcb如何隐藏和显示地线

    如何隐藏: 如何显示: 按下N后

  5. Javascript和jquery事件--鼠标右键事件,contextmenu

    右键点击触发是浏览器的默认菜单事件contextmenu,你可以选择阻止它,使用event.preventDefault();或者return false;. 想要定义右键点击事件,关注的是mouse ...

  6. POJ 2236 Wireless Network ||POJ 1703 Find them, Catch them 并查集

    POJ 2236 Wireless Network http://poj.org/problem?id=2236 题目大意: 给你N台损坏的电脑坐标,这些电脑只能与不超过距离d的电脑通信,但如果x和y ...

  7. GO语言学习(二)Windows 平台下 LiteIDE 的安装和使用

    1. 安装 Go 语言并设置环境变量 参考GO语言学习(一) 2. MinGW 的下载和安装 Windows 下的 Go 调试还需要安装 MinGW. 2.1 下载安装工具的安装 最新版本下载安装工具 ...

  8. Eclipse中开发环境也想把Tomcat 的默认BIO模式改为NIO模式

    1.1 问题 有时候,开发环境我们也想把Tomcat 的默认BIO模式改为NIO模式,该如何改呢? 1.2 方案 通过eclipse里面的server.xml进行修改. 1.3 步骤 首先我们来一起看 ...

  9. [D3] Basic Interactivity with D3 v4

    Data visualizations are a lot more interesting when they’re interactive. Whether it’s clicks, roll o ...

  10. [Angular2 Router] Redirects and Path Matching - Avoid Common Routing Pitfall

    In this tutorial we are going to learn how we can can configure redirects in the angular 2 router co ...