Description

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

Input

第一行为两个整数N,M。M是询问数,N是序列的长度(N<=100000,M<=200000)

第二行为N个整数,描述这个序列{ai},其中所有1<=ai<=N

再下面M行,每行两个整数x,y,

询问区间[l,r]由下列规则产生(OIER都知道是怎样的吧>_<):

l=min((x+lastans)mod n+1,(y+lastans)mod n+1);

r=max((x+lastans)mod n+1,(y+lastans)mod n+1);

Lastans表示上一个询问的答案,一开始lastans为0

Output

一共M行,每行给出每个询问的答案。

Sample Input

10 10
6 4 9 10 9 10 9 4 10 4
3 8
10 1
3 4
9 4
8 1
7 8
2 9
1 1
7 3
9 9

Sample Output

4
10
10
0
0
10
0
4
0
4

HINT

注意出题人为了方便,input的第二行最后多了个空格。

2015.6.24新加数据一组,2016.7.9放至40S,600M,但未重测

Source


  题目大意 询问区间内只出现1次数的最大值。强制在线。

  考虑每位置上的数会对哪些询问作出贡献。

  显然要让位置i对答案产生贡献询问的区间需要满足 pre[i] < l <= i 并且 i <= r < suf[i] 。

  那么就可以将每个询问(l, r)看成二维平面内的一个点。

  这样的话,每个位置对答案的贡献就可以通过2维线段树来进行维护。

  为了防止MLE,所以采取标记永久化的方案。但是注意修改操作是和线段树维护的信息取max。

Code

  1. /**
  2. * bzoj
  3. * Problem#3489
  4. * Accepted
  5. * Time: 21836ms
  6. * Memory: 227780k
  7. */
  8. #include <bits/stdc++.h>
  9. using namespace std;
  10. typedef bool boolean;
  11.  
  12. typedef class SegTreeNode {
  13. public:
  14. SegTreeNode* val;
  15. SegTreeNode *l, *r;
  16.  
  17. SegTreeNode(int val = ):val((SegTreeNode*)val) { }
  18. SegTreeNode(int val, SegTreeNode* org):val((SegTreeNode*)val) {
  19. l = r = org;
  20. }
  21.  
  22. int intvalue() {
  23. return (int)val;
  24. }
  25.  
  26. SegTreeNode*& pnodeval() {
  27. return val;
  28. }
  29.  
  30. void set(int x) {
  31. val = (SegTreeNode*)x;
  32. }
  33. }SegTreeNode;
  34.  
  35. #define PLimit 10000000
  36.  
  37. //int alloced = 0;
  38. SegTreeNode pool[PLimit];
  39. SegTreeNode null = SegTreeNode(, &null);
  40. SegTreeNode* top = pool;
  41.  
  42. SegTreeNode* newnode() {
  43. // alloced++;
  44. if(top >= pool + PLimit)
  45. return new SegTreeNode(, &null);
  46. *top = SegTreeNode(, &null);
  47. return top++;
  48. }
  49.  
  50. typedef class SegTree {
  51. public:
  52. int n;
  53. SegTreeNode* rt;
  54.  
  55. SegTree() { }
  56. SegTree(int n):n(n), rt(newnode()) { }
  57.  
  58. void update2(SegTreeNode*& node, int l, int r, int ql, int qr, int val) {
  59. if(node == &null || node == NULL)
  60. node = newnode();
  61. if(l == ql && r == qr) {
  62. if(val > node->intvalue())
  63. node->set(val);
  64. return;
  65. }
  66. int mid = (l + r) >> ;
  67. if(ql <= mid)
  68. update2(node->l, l, mid, ql, (qr > mid) ? (mid) : (qr), val);
  69. if(qr > mid)
  70. update2(node->r, mid + , r, (ql > mid) ? (ql) : (mid + ), qr, val);
  71. }
  72.  
  73. void update(SegTreeNode*& node, int l, int r, int ql, int qr, int qx, int qy, int val) {
  74. if(node == &null)
  75. node = newnode();
  76. if(l == ql && r == qr) {
  77. update2(node->pnodeval(), , n, qx, qy, val);
  78. return;
  79. }
  80. int mid = (l + r) >> ;
  81. if(ql <= mid)
  82. update(node->l, l, mid, ql, (qr > mid) ? (mid) : (qr), qx, qy, val);
  83. if(qr > mid)
  84. update(node->r, mid + , r, (ql > mid) ? (ql) : (mid + ), qr, qx, qy, val);
  85. }
  86.  
  87. int query2(SegTreeNode*& node, int l, int r, int idx) {
  88. if(node == NULL || node == &null)
  89. return ;
  90. if(l == idx && r == idx)
  91. return node->intvalue();
  92. int mid = (l + r) >> , rt = node->intvalue(), cmp = ;
  93. if(idx <= mid)
  94. cmp = query2(node->l, l, mid, idx);
  95. else
  96. cmp = query2(node->r, mid + , r, idx);
  97. return (cmp > rt) ? (cmp) : (rt);
  98. }
  99.  
  100. int query(SegTreeNode*& node, int l, int r, int idx, int bidx) {
  101. if(node == &null)
  102. return ;
  103. if(l == idx && r == idx)
  104. return query2(node->pnodeval(), , n, bidx);
  105. int mid = (l + r) >> , rt = query2(node->pnodeval(), , n, bidx), cmp;
  106. if(idx <= mid)
  107. cmp = query(node->l, l, mid, idx, bidx);
  108. else
  109. cmp = query(node->r, mid + , r, idx, bidx);
  110. return (cmp > rt) ? (cmp) : (rt);
  111. }
  112. }SegTree;
  113.  
  114. int n, m;
  115. int *ar;
  116. int *pre, *suf;
  117. int *head;
  118. SegTree st;
  119.  
  120. inline void init() {
  121. scanf("%d%d", &n, &m);
  122. st = SegTree(n);
  123. ar = new int[(n + )];
  124. pre = new int[(n + )];
  125. suf = new int[(n + )];
  126. head = new int[(n + )];
  127. for(int i = ; i <= n; i++)
  128. scanf("%d", ar + i);
  129. }
  130.  
  131. inline void solve() {
  132. memset(head, , sizeof(int) * (n + ));
  133. for(int i = ; i <= n; i++)
  134. pre[i] = head[ar[i]], head[ar[i]] = i;
  135. fill(head, head + n + , n + );
  136. for(int i = n; i; i--)
  137. suf[i] = head[ar[i]], head[ar[i]] = i;
  138.  
  139. for(int i = ; i <= n; i++)
  140. st.update(st.rt, , n, pre[i] + , i, i, suf[i] - , ar[i]);//, fprintf(stderr, "%d: Memory Usage: %d (%d nodes)\n", i, alloced * sizeof(SegTreeNode), alloced);
  141. int lastans = , x, y;
  142. while(m--) {
  143. scanf("%d%d", &x, &y);
  144. x = (x + lastans) % n + ;
  145. y = (y + lastans) % n + ;
  146. if(x > y) swap(x, y);
  147. lastans = st.query(st.rt, , n, x, y);
  148. printf("%d\n", lastans);
  149. }
  150. }
  151.  
  152. int main() {
  153. init();
  154. solve();
  155. return ;
  156. }

bzoj 3489 A simple rmq problem - 线段树的更多相关文章

  1. bzoj 3489: A simple rmq problem k-d树思想大暴力

    3489: A simple rmq problem Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 551  Solved: 170[Submit][ ...

  2. bzoj 3489 A simple rmq problem——主席树套线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题解:http://www.itdaan.com/blog/2017/11/24/9b ...

  3. BZOJ.3489.A simple rmq problem(主席树 Heap)

    题目链接 当时没用markdown写,可能看起来比较难受...可以复制到别的地方看比如DevC++. \(Description\) 给定一个长为n的序列,多次询问[l,r]中最大的只出现一次的数.强 ...

  4. bzoj 3489 A simple rmq problem —— 主席树套线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题解:http://www.itdaan.com/blog/2017/11/24/9b ...

  5. BZOJ 3489: A simple rmq problem

    3489: A simple rmq problem Time Limit: 40 Sec  Memory Limit: 600 MBSubmit: 1594  Solved: 520[Submit] ...

  6. BZOJ 3489 A simple rmq problem 可持久化KDtree/二维线段树

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题意概述: 给出一个序列,每次询问一个序列区间中仅出现了一次的数字最大是多少,如果 ...

  7. [BZOJ 3489] A simple rmq problem 【可持久化树套树】

    题目链接:BZOJ - 3489 题目分析 “因为是OJ上的题,就简单点好了.”——出题人 真的..好..简单... 首先,我们求出每个数的前一个与它相同的数的位置,即 prev[i] ,如果前面没有 ...

  8. BZOJ 3489 A simple rmq problem(可持久化线段树)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3489 题意:一个数列.每次询问一个区间内出现一次的最大的数字是多少. 思路:设la ...

  9. BZOJ 3489: A simple rmq problem (KD-tree做法)

    KD树水过这道可持久化树套树-其实就是个三维偏序 题解戳这里 CODE #include <bits/stdc++.h> using namespace std; #define ls ( ...

随机推荐

  1. vue中打印显示++的问题解决方案(做成类似同步的操作就行了)

    这个问题,困扰我很久很久 怎么实现的呢?首先进入页面就开始调取打印接口,打印接口的成功回调函数里面写 this.hasOut++(这是实时显示的数量)this.width=(this.hasOut/t ...

  2. System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.InvalidOperationException: 超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。

    2017/8/15 20:55:21 [AgentPayQuery_205506102_1BBBB]系统异常:System.Data.Entity.Core.EntityException: The ...

  3. G 面经 && Leetcode: Longest Repeating Character Replacement

    Given a string that consists of only uppercase English letters, you can replace any letter in the st ...

  4. ACM-彩票

    题目描述 OMeGa 兄弟最近赢了巨奖!但当他们在分彩票奖金的时候却遇到了一些问题.他们两兄弟对一切偶数都痴迷不已,以至于在分奖金的时候,他们两个都希望自己分到的钱是偶数(即便两人分的钱不一样也没关系 ...

  5. Javascript-for循环案例-打印1-100之间所有的数字

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  6. netframework转core时文件响应流问题

    做将framework webapi项目转成netcore平台上的webapi项目时,发现原来的返回文件响应流在netcore平台下失效.代码如下,返回pdf文件响应流,供前端显示 /// <s ...

  7. 《大话设计模式》c++实现 建造者模式

    一.UML图 关键词:Subject维护一个Observer列表,Subject执行Notify()时就执行列表中的每个Observer的Update(). 二.概念 观察者模式:定义了一种一对多的依 ...

  8. 概念、DW介绍

    网页设计知识点大致分为五个部分,分别是: 1.概念.DW介绍: 2.标签: 3.样式表CSS: 4.JQuery: 5.JavaScript 概念.DW介绍: 一.网页的基本结构 <!--文档声 ...

  9. string 常量池 栈 堆

  10. Firefox 功能笔记

    1.复制标签 说明:复制标签功能即新开一个与当前页一样的标签页,这个功能在Chrome中点击标签右键复制即可,但是在firefox中没有 Firefox中实现:Ctrl+拖动标签页