【BZOJ3489】 A simple rmq problem
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
Solution
三维偏序。可以看做位置在一个区间内,上一个在区间外,下一个也在区间外的的数的最大值。我们发现有一维是前缀(上一个出现的位置)所以这一维就可以可持久化,剩下两维就树套树咯。。。复杂度O(nlog^2)
Code
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 #define R register 6 #define maxn 100010 7 #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) 8 #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) 9 10 inline int F() 11 { 12 R int cnt = 0; R char ch; 13 while (ch = getchar(), ch < '0' || ch > '9') ; 14 cnt = ch - '0'; 15 while (ch = getchar(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; 16 return cnt; 17 } 18 int next[maxn], prev[maxn], last[maxn], r[maxn], n, a[maxn]; 19 inline bool cmp(R int a, R int b) { return prev[a] < prev[b];} 20 struct Seg2 { 21 Seg2 *ls, *rs; 22 int mx; 23 } mem2[maxn * 450], *tot2 = mem2; 24 struct Seg1 { 25 Seg1 *ls, *rs; 26 Seg2 *x; 27 } *rt[maxn], mem1[maxn * 30], *tot1 = mem1; 28 Seg2 *insert2(R Seg2 *lst, R int l, R int r, R int x, R int v) 29 { 30 R Seg2 *now = ++tot2; 31 now -> mx = dmax(lst -> mx, v); 32 if (l == r) return now; 33 R int mid = l + r >> 1; 34 if (x <= mid) 35 { 36 now -> rs = lst -> rs; 37 now -> ls = insert2(lst -> ls, l, mid, x, v); 38 } 39 else 40 { 41 now -> ls = lst -> ls; 42 now -> rs = insert2(lst -> rs, mid + 1, r, x, v); 43 } 44 return now; 45 } 46 Seg1 *insert1(R Seg1 *lst, R int l, R int r, R int x) 47 { 48 R Seg1 *now = ++tot1; 49 now -> x = insert2(lst -> x, 1, n + 1, next[x], a[x]); 50 if (l == r) return now; 51 R int mid = l + r >> 1; 52 if (x <= mid) 53 { 54 now -> rs = lst -> rs; 55 now -> ls = insert1(lst -> ls, l, mid, x); 56 } 57 else 58 { 59 now -> ls = lst -> ls; 60 now -> rs = insert1(lst -> rs, mid + 1, r, x); 61 } 62 return now; 63 } 64 int query2(R Seg2 *now, R int l, R int r, R int x) 65 { 66 if (l == r || now == mem2) return now -> mx; 67 R int mid = l + r >> 1, ret = 0, tmp; 68 if (x <= mid) 69 { 70 cmax(ret, now -> rs -> mx); 71 tmp = query2(now -> ls, l, mid, x); 72 cmax(ret, tmp); 73 } 74 else 75 { 76 tmp = query2(now -> rs, mid + 1, r, x); 77 cmax(ret, tmp); 78 } 79 return ret; 80 } 81 int query1(R Seg1 *now, R int l, R int r, R int ql, R int qr) 82 { 83 if (ql <= l && r <= qr) return query2(now -> x, 1, n + 1, qr + 1); 84 R int mid = l + r >> 1, tmp, ret = 0; 85 if (ql <= mid) tmp = query1(now -> ls, l, mid, ql, qr), cmax(ret, tmp); 86 if (mid < qr) tmp = query1(now -> rs, mid + 1, r, ql, qr), cmax(ret, tmp); 87 return ret; 88 } 89 int main() 90 { 91 R int m; n = F(); m = F(); 92 mem1 -> ls = mem1 -> rs = mem1; mem1 -> x = mem2; 93 mem2 -> ls = mem2 -> rs = mem2; 94 for (R int i = 1; i <= n; ++i) 95 { 96 a[i] = F(); 97 r[i] = i; 98 prev[i] = last[a[i]]; 99 next[last[a[i]]] = i; 100 last[a[i]] = i; 101 } 102 for (R int i = 1; i <= n; ++i) last[i] ? next[last[i]] = n + 1 : 0; 103 std::sort(r + 1, r + n + 1, cmp); 104 rt[0] = mem1; 105 for (R int i = 1; i <= n; ++i) 106 { 107 R int now = r[i]; 108 if (prev[now] == 0) rt[0] = insert1(rt[0], 0, n, now); 109 else rt[prev[now]] = insert1(rt[prev[r[i - 1]]], 0, n, now); 110 } 111 for (R int i = 1; i <= n; ++i) if (!rt[i]) rt[i] = rt[i - 1]; 112 R int ans = 0; 113 for (R int i = 1; i <= m; ++i) 114 { 115 R int l = F(), r = F(); 116 (l += ans) %= n; (r += ans) %= n; 117 l > r ? std::swap(l, r), 1 : 0; ++l; ++r; 118 // printf("l = %d r = %d\n", l, r); 119 printf("%d\n", ans = query1(rt[l - 1], 0, n, l, r)); 120 } 121 return 0; 122 }