bzoj3489
kdtree
3维kdtree,就是三个维度轮换着切,我们把每个元素看成一个点,坐标是上次出现的位置,下次出现的位置,自己的位置,第一个<l,第二个>r,第三个[l,r],然后kdtree上爆搜剪枝就行了。
kdtree看起来能解决所有偏序问题。
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 5, inf = 1e9; int rd() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f; } int n, m, root, d, ans; int last[N]; struct data { int p[3], mn[3], mx[3], lc, rc, ans, val; bool friend operator < (const data &a, const data &b) { if(a.p[d] != b.p[d]) return a.p[d] < b.p[d]; if(a.p[(d + 1) % 3] != b.p[(d + 1) % 3]) return a.p[(d + 1) % 3] < b.p[(d + 1) % 3]; if(a.p[(d + 2) % 3] != b.p[(d + 2) % 3]) return a.p[(d + 2) % 3] < b.p[(d + 2) % 3]; } } a[N]; void update(int x) { int lc = a[x].lc, rc = a[x].rc; for(int i = 0; i < 3; ++i) { a[x].mn[i] = min(a[x].p[i], min(a[lc].mn[i], a[rc].mn[i])); a[x].mx[i] = max(a[x].p[i], max(a[lc].mx[i], a[rc].mx[i])); } a[x].ans = max(a[x].val, max(a[lc].ans, a[rc].ans)); } int build(int l, int r, int D) { if(l > r) return 0; d = D; int mid = (l + r) >> 1; nth_element(a + l, a + mid, a + r + 1); a[mid].lc = build(l, mid - 1, (D + 1) % 3); a[mid].rc = build(mid + 1, r, (D + 1) % 3); update(mid); return mid; } bool out(int k, int l, int r) { return ans < a[k].ans && a[k].mn[0] <= r && a[k].mx[0] >= l && a[k].mn[1] < l && a[k].mx[2] > r; } void query(int k, int l, int r) { if(!k || !out(k, l, r)) return; if(a[k].mx[0] <= r && a[k].mn[0] >= l && a[k].mx[1] < l && a[k].mn[2] > r) { ans = max(ans, a[k].ans); return; } if(a[k].p[0] <= r && a[k].p[0] >= l && a[k].p[1] < l && a[k].p[2] > r) ans = max(ans, a[k].val); query(a[k].lc, l, r); query(a[k].rc, l, r); } int main() { for(int i = 0; i < 3; ++i) a[0].mn[i] = inf, a[0].mx[i] = a[0].ans = -inf; n = rd(); m = rd(); for(int i = 1; i <= n; ++i) { a[i].val = rd(); a[i].p[0] = i; a[i].p[1] = last[a[i].val]; a[last[a[i].val]].p[2] = i; last[a[i].val] = i; } for(int i = 1; i <= n; ++i) if(!a[i].p[2]) a[i].p[2] = n + 1; root = build(1, n, 0); while(m--) { int l = (rd() + ans) % n + 1, r = (rd() + ans) % n + 1; if(l > r) swap(l, r); ans = 0; query(root, l, r); printf("%d\n", ans); } return 0; }