链接

http://codeforces.com/contest/484/problem/E

题意

给出 n 个宽度为 1 ,高度为 h[i] 的矩形,从 1 到 n 连续挨着排。有 m 次询问,每次询问一段区间 [l, r] 中组成宽度为 w 的矩形的最高高度是多少?(n, m ≤ 1e5, h[i] ≤ 1e9)

思路

自己没想到。听子卿讲题解。

二分答案

二分答案 h,判定 [l, r] 内不低于 h 的矩形是否有连续 w 个。

对于固定 h 的判定问题,我们只要建立一颗线段树,区间存内部大于等于 h 的最长区间长度,靠左靠右的最长区间长度还有本区间长度,进行区间合并。查询 [l, r] 最长连续长度,如果大于等于 w 那么判断就通过。

可持久化

有了上述分析,这个问题要解决的话,只要把对应每个高度的线段树都建立出来就可以了。但是一颗一颗建立显然是不允许的。

注意到线段树之间有共用关系,比如数据是:1 2 2 3。如果对应高度 3 建立了线段树,那么高度为 2 对应的线段树可以看做是高度 3 的线段树进行单点更新(两次)的结果。

如此一来,我们可以将线段树可持久化,解决线段树的建立问题。

复杂度容易知道是:,可以通过该题。

错误

我昨晚写这个题的时候犯了个错误,导致一直没过。

错误主要原因是建树出错,从前建树为了节省时间和内存,函数式的起始树我不会完整的建立,而是用一个点代替,所有要访问这个起始树的都访问到这一个节点。一般这个节点的标号是 0,左右儿子的标号也是 0。起始树当然标记成 root[0] = 0。

但是没有深刻的认识到这个技巧只能用于空树的所有节点的值都相同的状况。对于这个题目,因为我对每个点存了本区间长度,所以是不能这样用的。

代码

  1. // c head files


  2. #include <stdio.h> 

  3. #include <assert.h> 

  4. // c++ head files 

  5. #include <algorithm> 

  6. using std::max; 

  7. using std::sort; 

  8. using std::unique; 

  9. #include <iostream> 

  10. using std::cout; 

  11. using std::endl; 


  12. const int MAXN = 100000 + 5; 

  13. const int LOG = 20; 

  14. const int MAXT = LOG * MAXN; 


  15. namespace FST 



  16. struct TNode 



  17. int len; 

  18. int lenL; 

  19. int lenR; 

  20. int lenMax; 


  21. int lson; 

  22. int rson; 

  23. } tree[MAXT]; 


  24. int nodeCnt = 0; 


  25. typedef TNode& ref; 

  26. typedef const ref cref; 


  27. void push(cref l, cref r, ref now) 



  28. now.len = l.len + r.len; 

  29. now.lenMax = max(max(l.lenMax, r.lenMax), l.lenR + r.lenL); 

  30. now.lenL = l.lenL + (l.lenL == l.len ? r.lenL : 0); 

  31. now.lenR = r.lenR + (r.lenR == r.len ? l.lenR : 0); 




  32. void push(ref now) 



  33. int l = now.lson; 

  34. int r = now.rson; 

  35. push(tree[l], tree[r], now); 




  36. void init(int& now, int l, int r) 



  37. now = nodeCnt++; 

  38. if (l == r) { 

  39. tree[now].len = 1; 

  40. tree[now].lenL = 0; 

  41. tree[now].lenR = 0; 

  42. tree[now].lenMax = 0; 

  43. return; 



  44. int mid = (l + r) >> 1; 

  45. init(tree[now].lson, l, mid); 

  46. init(tree[now].rson, mid + 1, r); 

  47. push(tree[now]); 




  48. void init(int n, int& root0) 



  49. nodeCnt = 0; 

  50. init(root0, 1, n); 




  51. void update(int& now, int l, int r, int i) 



  52. tree[nodeCnt] = tree[now]; 

  53. now = nodeCnt++; 

  54. assert(nodeCnt < MAXT); 

  55. if (l == r) { 

  56. tree[now].len = 1; 

  57. tree[now].lenL = 1; 

  58. tree[now].lenR = 1; 

  59. tree[now].lenMax = 1; 

  60. return; 



  61. int mid = (l + r) >> 1; 

  62. if (i <= mid) 

  63. update(tree[now].lson, l, mid, i); 

  64. else update(tree[now].rson, mid + 1, r, i); 

  65. push(tree[now]); 

  66. assert(tree[now].len == (r - l + 1)); 




  67. TNode query(int now, int l, int r, int ql, int qr) 



  68. if (ql == l && qr == r) 

  69. return tree[now]; 

  70. int mid = (l + r) >> 1; 

  71. if (qr <= mid) 

  72. return query(tree[now].lson, l, mid, ql, qr); 

  73. if (ql > mid) 

  74. return query(tree[now].rson, mid + 1, r, ql, qr); 


  75. TNode lson, rson, result; 

  76. lson = query(tree[now].lson, l, mid, ql, mid); 

  77. rson = query(tree[now].rson, mid + 1, r, mid + 1, qr); 

  78. push(lson, rson, result); 

  79. return result; 




  80. int query(int now, int n, int ql, int qr) 



  81. return query(now, 1, n, ql, qr).lenMax; 






  82. using FST::query; 

  83. using FST::update; 

  84. using FST::init; 


  85. struct Node 



  86. int value; 

  87. int index; 

  88. } a[MAXN]; 


  89. int value[MAXN]; 

  90. int root[MAXN]; 


  91. bool cmp(const Node& a, const Node& b) 



  92. return a.value < b.value; 




  93. int main() 



  94. #ifndef ONLINE_JUDGE 

  95. freopen("data.in", "r", stdin); 

  96. #endif // ONLINE_JUDGE 

  97. int n; 

  98. int cnt; 

  99. scanf("%d", &n); 

  100. for (int i = 1; i <= n; i++) { 

  101. scanf("%d", &a[i].value); 

  102. a[i].index = i; 

  103. value[i] = a[i].value; 



  104. sort(a + 1, a + n + 1, cmp); 

  105. sort(value + 1, value + n + 1); 

  106. cnt = unique(value + 1, value + n + 1) - (value + 1); 

  107. init(n, root[0]); 

  108. for (int i = cnt, j = n; i >= 1; i--) { 

  109. root[i] = root[(i + 1) % (cnt + 1)]; 

  110. for (; j >= 1 && a[j].value == value[i]; j--) 

  111. update(root[i], 1, n, a[j].index); 




  112. int m; 

  113. int l, r, w; 

  114. int low, upp, mid; 

  115. scanf("%d", &m); 

  116. for (; m--; ) { 

  117. scanf("%d %d %d", &l, &r, &w); 

  118. low = 0; 

  119. upp = cnt + 1; 

  120. // [low, upp) 

  121. for (; upp - low > 1; ) { 

  122. mid = (low + upp) >> 1; 

  123. if (query(root[mid], n, l, r) >= w) 

  124. low = mid; 

  125. else upp = mid; 



  126. printf("%d\n", value[low]); 



  127. return 0; 



转载于:https://www.cnblogs.com/gu-castle/p/5507707.html

CODEFORCES 484E Sign on Fence相关推荐

  1. Codeforces 484E Sign on Fence(是持久的段树+二分法)

    题目链接:Codeforces 484E Sign on Fence 题目大意:给定给一个序列,每一个位置有一个值,表示高度,如今有若干查询,每次查询l,r,w,表示在区间l,r中, 连续最长长度大于 ...

  2. CodeForces - 484E Sign on Fence(主席树区间合并+二分)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的数列,需要回答 mmm 次询问,每次询问的格式如下: lrkl\ r\ kl r k,需要回答区间 [l,r][l,r][l,r] 内,所有长度 ...

  3. CFCC百套计划4 Codeforces Round #276 (Div. 1) E. Sign on Fence

    http://codeforces.com/contest/484/problem/E 题意: 给出n个数,查询最大的在区间[l,r]内,长为w的子区间的最小值 第i棵线段树表示>=i的数 维护 ...

  4. E. Sign on Fence(整体二分 + 线段树维护区间最大连续 1 的个数)

    E. Sign on Fence 给定一个长度为nnn的数组aaa,1≤ai≤1091 \leq a_i \leq 10 ^ 91≤ai​≤109,有mmm次询问,每次给定l,r,kl, r, kl, ...

  5. 【CodeForces - 270A】Fancy Fence (几何,思维,水题)

    题干: Emuskald needs a fence around his farm, but he is too lazy to build it himself. So he purchased ...

  6. CF484E Sign on Fence

    题意 给定一个长度为n的数列,有m次询问,询问形如l r k 要你在区间[l,r]内选一个长度为k的区间,求区间最小数的最大值 Sol 二分答案 怎么判定,每种数字开一棵线段树 某个位置上的数大于等于 ...

  7. servlet向ajax传递数据库,一、JSP、servlet、SQL三者之间的数据传递(前台与后台数据交互)...

    背景: 目前业界很流行的MVC(model-view-control)开发模式,理解为 模型是Bean, 视图是 Html/Jsp, 控制是Servlet, 关联数据库的Dao web的运行机制: 数 ...

  8. [kuangbin]各种各样的题单

    [kuangbin]各种各样的题单 专题1 简单搜索 POJ 1321 POJ 2251 POJ 3278 POJ 3279 POJ 1426 POJ 3126 POJ 3087 POJ 3414 F ...

  9. 可持久化汇总(讲解+题目)

    可持久化(一) 可持久化(二) 可持久化3–可持久化01Trie 可持久化4–可持久化并查集 各模块的例题都在各自讲解下面有写 下面是加强练习 练习题讲解--肖然老师的博客 练习题: P4137 Rm ...

最新文章

  1. Ogre 2011-11-29
  2. lucene 学习一
  3. 获取图片中感兴趣区域的信息(Matlab实现)
  4. 京东智联云分布式低延时RTC系统
  5. 写出python字符串三种常用的函数或方法_python中几种常用字符串函数
  6. 大一下学期的自我目标
  7. MySQL 8个character_set变量的基本作用
  8. 论文笔记_S2D.20_2017-ICCV-从单张RGB图像到精确尺度深度图评估的一种双支网络
  9. textfield tips
  10. add p4 多个文件_Python实例:对文件夹图片批量添加logo操作
  11. Android通过ping操作进行网络检测,并返回花费的时间
  12. 斐讯k3c V1.7D frp升级
  13. 【最优化方法】K-Means聚类实验:Python实现手写数字图像MNIST分类
  14. Working with Qt maya2011
  15. 用c语言编写出的情话,c语言for情话
  16. 小白的RFID宿舍智能锁
  17. python 中 np.sum()函数 通俗易懂理解!
  18. 使markdown文档中的图片居中
  19. 怎么查看服务器的性能,查看服务器进程性能查看
  20. YOLO(You Only Look Once)算法详解

热门文章

  1. 以远程桌面访问Windows Azure虚拟机(转+译)
  2. CCNet 的 Build 流程
  3. js事件循环 microtask macrotask
  4. codefirst数据库迁移
  5. PAT 1041. 考试座位号(15)
  6. WCF-学习笔记概述之计算服务(1)
  7. Linux内核编译和测试
  8. DataBinding的双向绑定实现原理
  9. 一名Android程序员如何减少代码中该死的-if-else-嵌套,怎么让代码更简洁?
  10. android studio 编译报错:download fastutil-7.2.0.jar