【题解】A simple RMQ problem

占坑,免得咕咕咕了,争取在2h内写出代码

upd:由于博主太菜而且硬是要用指针写两个主席树,所以延后2hQAQ

upd:由于博主太菜而且太懒所以他决定写kd tree了

upd:由于博主太菜而且太懒所以他不写代码了(实际上是写了6k之后崩溃了)

所以直接口胡题解


题目大意:

  1. 因为是OJ上的题,就简单点好了。给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大。如果找不到这样的数,则直接输出0。我会采取一些措施强制在线。

好就是这样

解法:

我本来是想直接对值域线段树可持久化,然后类似于吉司机线段树一样维护最小值和次小值...发现不会查一个区间,于是我们可以这样:

每个位置记录i一个上一次出现的\(pre\)和下一次出现的\(next\),把所有数先按照\(pre\)从小往大排序,对于每一个位置,维护一个数组,数组的下标是next[i],数组里面的值是data[i],查询的时候查询查询这个数组\([r+1,n+1]\)中的最大值是多少,就是我们的答案。可持久化数组可以用主席树维护,前缀\(pre\)的\(next\)可以用主席树维护,所以只要主席树套主席树就\(ok\)了。

时空复杂度\(O(n \log^2 n)\)

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <cmath>
  6. #include <algorithm>
  7. using namespace std;
  8. inline void Read(int &Num) {
  9. char c = getchar();
  10. bool Neg = false;
  11. while (c < '0' || c > '9') {
  12. if (c == '-')
  13. Neg = true;
  14. c = getchar();
  15. }
  16. Num = c - '0';
  17. c = getchar();
  18. while (c >= '0' && c <= '9') {
  19. Num = Num * 10 + c - '0';
  20. c = getchar();
  21. }
  22. if (Neg)
  23. Num = -Num;
  24. }
  25. inline int gmin(int a, int b) { return a < b ? a : b; }
  26. inline int gmax(int a, int b) { return a > b ? a : b; }
  27. const int MaxN = 100000 + 5, MaxNodeI = 2000000 + 5, MaxNodeII = 40000000 + 5;
  28. int n, m, Ans, IndexI, IndexII;
  29. int Last[MaxN], Root_I[MaxN], Son_I[MaxNodeI][2], Root_II[MaxNodeI], Son_II[MaxNodeII][2], T[MaxNodeII];
  30. struct ES {
  31. int Pos, Num, Prev, Next;
  32. bool operator<(const ES &b) const { return Prev < b.Prev; }
  33. bool operator<(const int &b) const { return Prev < b; }
  34. } E[MaxN];
  35. void Insert_II(int &x, int Last, int s, int t, int Pos, int Num) {
  36. if (x == 0)
  37. x = ++IndexII;
  38. T[x] = gmax(T[Last], Num);
  39. if (s == t)
  40. return;
  41. int m = (s + t) >> 1;
  42. if (Pos <= m) {
  43. Son_II[x][1] = Son_II[Last][1];
  44. Insert_II(Son_II[x][0], Son_II[Last][0], s, m, Pos, Num);
  45. } else {
  46. Son_II[x][0] = Son_II[Last][0];
  47. Insert_II(Son_II[x][1], Son_II[Last][1], m + 1, t, Pos, Num);
  48. }
  49. }
  50. void Insert_I(int &x, int Last, int s, int t, int Nxt, int Pos, int Num) {
  51. if (x == 0)
  52. x = ++IndexI;
  53. Insert_II(Root_II[x], Root_II[Last], 0, n + 1, Pos, Num);
  54. if (s == t)
  55. return;
  56. int m = (s + t) >> 1;
  57. if (Nxt <= m) {
  58. Son_I[x][1] = Son_I[Last][1];
  59. Insert_I(Son_I[x][0], Son_I[Last][0], s, m, Nxt, Pos, Num);
  60. } else {
  61. Son_I[x][0] = Son_I[Last][0];
  62. Insert_I(Son_I[x][1], Son_I[Last][1], m + 1, t, Nxt, Pos, Num);
  63. }
  64. }
  65. int Get_II(int x, int s, int t, int l, int r) {
  66. if (x == 0)
  67. return 0;
  68. if (l <= s && r >= t)
  69. return T[x];
  70. int ret = 0, m = (s + t) >> 1;
  71. if (l <= m)
  72. ret = gmax(ret, Get_II(Son_II[x][0], s, m, l, r));
  73. if (r >= m + 1)
  74. ret = gmax(ret, Get_II(Son_II[x][1], m + 1, t, l, r));
  75. return ret;
  76. }
  77. int Get_I(int x, int s, int t, int l_I, int r_I, int l_II, int r_II) {
  78. if (x == 0)
  79. return 0;
  80. if (l_I <= s && r_I >= t)
  81. return Get_II(Root_II[x], 0, n + 1, l_II, r_II);
  82. int ret = 0, m = (s + t) >> 1;
  83. if (l_I <= m)
  84. ret = gmax(ret, Get_I(Son_I[x][0], s, m, l_I, r_I, l_II, r_II));
  85. if (r_I >= m + 1)
  86. ret = gmax(ret, Get_I(Son_I[x][1], m + 1, t, l_I, r_I, l_II, r_II));
  87. return ret;
  88. }
  89. int main() {
  90. scanf("%d%d", &n, &m);
  91. for (int i = 1; i <= n; ++i) {
  92. Read(E[i].Num);
  93. E[i].Pos = i;
  94. E[i].Prev = Last[E[i].Num];
  95. E[E[i].Prev].Next = i;
  96. E[i].Next = n + 1;
  97. Last[E[i].Num] = i;
  98. }
  99. sort(E + 1, E + n + 1);
  100. for (int i = 1; i <= n; ++i) Insert_I(Root_I[i], Root_I[i - 1], 0, n + 1, E[i].Next, E[i].Pos, E[i].Num);
  101. Ans = 0;
  102. int x, y, l, r, p;
  103. for (int i = 1; i <= m; ++i) {
  104. Read(x);
  105. Read(y);
  106. l = gmin((x + Ans) % n + 1, (y + Ans) % n + 1);
  107. r = gmax((x + Ans) % n + 1, (y + Ans) % n + 1);
  108. p = lower_bound(E + 1, E + n + 1, l) - E - 1;
  109. Ans = Get_I(Root_I[p], 0, n + 1, r + 1, n + 1, l, r);
  110. printf("%d\n", Ans);
  111. }
  112. return 0;
  113. }

【题解】BZOJ3489 A Hard RMQ problem(主席树套主席树)的更多相关文章

  1. bzoj3489: A simple rmq problem (主席树)

    //========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/  转载要声明! //=============== ...

  2. BZOJ3489 A simple rmq problem 【可持久化树套树】*

    BZOJ3489 A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一 ...

  3. dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448

    4448: [Scoi2015]情报传递 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 588  Solved: 308[Submit][Status ...

  4. 【题解】P4585 [FJOI2015]火星商店问题(线段树套Trie树)

    [题解]P4585 [FJOI2015]火星商店问题(线段树套Trie树) 语文没学好不要写省选题面!!!! 题目大意: 有\(n\)个集合,每个集合有个任意时刻都可用的初始元素.现在有\(m\)个操 ...

  5. BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)

    题目描述 Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的 ...

  6. ZJOI 2017 树状数组(线段树套线段树)

    题意 http://uoj.ac/problem/291 思路 不难发现,九条カレン醬所写的树状数组,在查询区间 \([1,r]\) 的时候,其实在查询后缀 \([r,n]\) :在查询 \([l,r ...

  7. 【bzoj3217】ALOEXT 替罪羊树套Trie树

    题目描述 taorunz平时最喜欢的东西就是可移动存储器了……只要看到别人的可移动存储器,他总是用尽一切办法把它里面的东西弄到手. 突然有一天,taorunz来到了一个密室,里面放着一排可移动存储器, ...

  8. 【bzoj4785】[Zjoi2017]树状数组 线段树套线段树

    题目描述 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作 ...

  9. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

随机推荐

  1. Ioc(控制反转)、DI(依赖注入)

    一篇非常好的有关控制反转和依赖注入非常不错的文章,简单易通,与大家共同学习,这里只引用了一篇文章,还有很多相关的文章可以通过文章引用地址来看,相信大家看完理解的就比较深刻了 文章摘自:http://j ...

  2. Java设计模式-代理模式之动态代理(附源代码分析)

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  3. js Json操作

    JSON字符串: var jsonStr='{"fname":"json","fage":1}' JSON对象:    var jsonOb ...

  4. CenterOS卸载和安装MYSQL

    1.首先在命令行输入mysql,看一下本地计算机上是否有mysql. 2.卸载mysql服务: 首先查看安装的rpm的包:rpm –qa |grep mysql    对之前的服务进行删除.rpm – ...

  5. Extjs中设置只读的样式问题

    废话不多说,直接上代码:   view.down('#imageFile').hide(); view.down('#save_button').hide(); view.show(); view.d ...

  6. poj 2942 Knights of the Round Table(无向图的双连通分量+二分图判定)

    #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #includ ...

  7. Yarn源码分析之如何确定作业运行方式Uber or Non-Uber?

    在MRAppMaster中,当MapReduce作业初始化时,它会通过作业状态机JobImpl中InitTransition的transition()方法,进行MapReduce作业初始化相关操作,而 ...

  8. uva753 A Plug for UNIX 网络流最大流

    C - A Plug for UNIX    You are in charge of setting up the press room for the inaugural meeting of t ...

  9. 配置LANMP环境(5)-- 安装NGINX与配置

    安装nginx yum install nginx 若提示找不到nginx,则在软件源中添加nginx的软件源文件: vim /etc/yum.repos.d/nginx.repo 添加如下内容: [ ...

  10. vSphere共享存储全配置流程

    1.Openfiler的安装 Openfiler 由rPath Linux驱动,它是一个基于浏览器的免费网络存储管理实用程序,可以在单一框架中提供基于文件的网络连接存储 (NAS) 和基于块的存储区域 ...