【BZOJ3489】 A simple rmq problem

Description

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

Input

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

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

再下面M行,每行两个整数xy

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

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

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

Lastans表示上一个询问的答案,一开始lastans0

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

by zhzqkkk

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
", l, r);
119         printf("%d
", ans = query1(rt[l - 1], 0, n, l, r));
120     }
121     return 0;
122 } 
原文地址:https://www.cnblogs.com/cocottt/p/6780676.html