BZOJ 3489: A simple rmq problem
3489: A simple rmq problem
Time Limit: 40 Sec Memory Limit: 600 MBSubmit: 1594 Solved: 520
[Submit][Status][Discuss]
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
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
10
10
0
0
10
0
4
0
4
HINT
注意出题人为了方便,input的第二行最后多了个空格。
2015.6.24新加数据一组,2016.7.9放至40S,600M,但未重测
Source
参考了网上的一些做法,可持久化树套树什么的实在吃不消,于是采用了KD-Tree的方法。
考虑一个点,在哪个区间内它是唯一出现的呢?
设prev[i]为上一个和i处权值相同的位置,next[i]为下一个和i处权值相同的位置,显然在(prev[i],next[i])这个区间内,i点是该权值唯一出现的位置。
对于一个询问(ql,qr),我们可以转换为:找出满足 prev[i] < ql 且 next[i] > qr 且 ql <= i <= qr 的i中,权值最大的i。这个就是KD-Tree维护三维的区间最值问题。
1 #include <bits/stdc++.h> 2 3 inline int getC(void) { 4 static const int siz = 1024; 5 6 static char buf[siz]; 7 static char *hd = buf + siz; 8 static char *tl = buf + siz; 9 10 if (hd == tl) 11 fread(hd = buf, 1, siz, stdin); 12 13 return int(*hd++); 14 } 15 16 inline int getI(void) { 17 register int ret = 0; 18 register int neg = false; 19 register int bit = getC(); 20 21 for (; bit < 48; bit = getC()) 22 if (bit == '-')neg ^= true; 23 24 for (; bit > 47; bit = getC()) 25 ret = ret * 10 + bit - '0'; 26 27 return neg ? -ret : ret; 28 } 29 30 template <class T> 31 inline T min(const T &a, const T &b) { 32 return a < b ? a : b; 33 } 34 35 template <class T> 36 inline T max(const T &a, const T &b) { 37 return a > b ? a : b; 38 } 39 40 const int maxn = 100005; 41 42 int n, m; 43 int answer; 44 int num[maxn]; 45 46 int next[maxn]; 47 int prev[maxn]; 48 int last[maxn]; 49 50 int value[maxn][3]; 51 52 int pos[maxn]; 53 int maxv[maxn]; 54 int lson[maxn]; 55 int rson[maxn]; 56 int mini[maxn][3]; 57 int maxi[maxn][3]; 58 59 int qryL, qryR; 60 61 int cmpK; 62 63 inline bool cmp(const int &a, const int &b) { 64 return value[a][cmpK] < value[b][cmpK]; 65 } 66 67 int build(int l, int r, int k) { 68 int mid = (l + r) >> 1; cmpK = k; 69 std::nth_element( 70 pos + l, pos + mid, pos + r + 1, cmp); 71 maxv[mid] = num[pos[mid]]; 72 for (int i = 0; i < 3; ++i) 73 mini[mid][i] = maxi[mid][i] = value[pos[mid]][i]; 74 if (l < mid) { 75 lson[mid] = build(l, mid - 1, (k + 1) % 3); 76 maxv[mid] = max(maxv[mid], maxv[lson[mid]]); 77 for (int i = 0; i < 3; ++i) { 78 mini[mid][i] = min(mini[mid][i], mini[lson[mid]][i]); 79 maxi[mid][i] = max(maxi[mid][i], maxi[lson[mid]][i]); 80 } 81 } 82 if (r > mid) { 83 rson[mid] = build(mid + 1, r, (k + 1) % 3); 84 maxv[mid] = max(maxv[mid], maxv[rson[mid]]); 85 for (int i = 0; i < 3; ++i) { 86 mini[mid][i] = min(mini[mid][i], mini[rson[mid]][i]); 87 maxi[mid][i] = max(maxi[mid][i], maxi[rson[mid]][i]); 88 } 89 } 90 return mid; 91 } 92 93 inline bool check(int t) { 94 if (mini[t][0] > qryR || maxi[t][0] < qryL)return false; 95 if (mini[t][1] >= qryL || maxi[t][2] <= qryR)return false; 96 return true; 97 } 98 99 void query(int t) { 100 if (mini[t][0] >= qryL && maxi[t][0] <= qryR && maxi[t][1] < qryL && mini[t][2] > qryR) 101 { answer = max(answer, maxv[t]); return; } 102 if (pos[t] >= qryL && pos[t] <= qryR && prev[pos[t]] < qryL && next[pos[t]] > qryR) 103 answer = max(answer, num[pos[t]]); 104 if (maxv[lson[t]] > maxv[rson[t]]) { 105 if (lson[t] && maxv[lson[t]] > answer && check(lson[t]))query(lson[t]); 106 if (rson[t] && maxv[rson[t]] > answer && check(rson[t]))query(rson[t]); 107 } 108 else { 109 if (rson[t] && maxv[rson[t]] > answer && check(rson[t]))query(rson[t]); 110 if (lson[t] && maxv[lson[t]] > answer && check(lson[t]))query(lson[t]); 111 } 112 } 113 114 signed main(void) { 115 n = getI(); 116 m = getI(); 117 118 for (int i = 1; i <= n; ++i) 119 num[i] = getI(); 120 121 for (int i = 1; i <= n; ++i) 122 last[i] = 0; 123 124 for (int i = 1; i <= n; ++i) 125 prev[i] = last[num[i]], last[num[i]] = i; 126 127 for (int i = n; i >= 1; --i) 128 last[i] = n + 1; 129 130 for (int i = n; i >= 1; --i) 131 next[i] = last[num[i]], last[num[i]] = i; 132 133 for (int i = 1; i <= n; ++i) { 134 pos[i] = i; 135 value[i][0] = i; 136 value[i][1] = prev[i]; 137 value[i][2] = next[i]; 138 } 139 140 int root = build(1, n, 0); 141 142 for (int i = 1; i <= m; ++i) { 143 int x = getI(); 144 int y = getI(); 145 qryL = (x + answer) % n + 1; 146 qryR = (y + answer) % n + 1; 147 if (qryL > qryR) 148 qryL ^= (qryR ^= (qryL ^= qryR)); 149 answer = 0; query(root); printf("%d\n", answer); 150 } 151 }
@Author: YouSiki