【BZOJ】A simple rmq problem
阿新 • • 發佈:2018-12-27
【BZOJ】A simple rmq problem
題面
題解
這個題不強制線上的話隨便做啊。。。
考慮強制線上時怎麼搞
預處理出一個位置上一個出現的相同數的位置\(pre\)與下一個位置\(nxt\)
則對於一個詢問\([l,r]\)
一個位置\(i\)當且僅當\(pre_i<l\)且\(nxt_i>r\)
我們可以將一個位置看作一個點座標為\((pre_i,nxt_i)\)
要求橫座標\(<l\)且縱座標\(>r\)
這個可以用簡單\(kdTree\)
也可以用一個可持久化樹套樹強行維護一下
因為我寫的時候還不會\(KDT\),所以用可持久化樹套樹強行維護了一波
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <set> using namespace std; inline int gi() { register int data = 0, w = 1; register char ch = 0; while (!isdigit(ch) && ch != '-') ch = getchar(); if (ch == '-') w = -1, ch = getchar(); while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); return w * data; } const int MAX_N = 100005; int N, M; struct Number { int val, pre, nxt, id; } a[MAX_N]; bool operator < (const Number &l, const Number r) { return l.pre < r.pre; } struct Prestree { int ls, rs, rt; } t[MAX_N * 22]; struct SGT { int ls, rs, mx; } It[MAX_N * 18 * 18]; int rt[MAX_N], tot, cnt; void ins(int &o, int p, int l, int r, int pos, int v) { o = ++tot; It[o] = It[p], It[o].mx = max(It[o].mx, v); if (l == r) return ; int mid = (l + r) >> 1; if (pos <= mid) ins(It[o].ls, It[p].ls, l, mid, pos, v); else ins(It[o].rs, It[p].rs, mid + 1, r, pos, v); } void insert(int &o, int p, int l, int r, Number v) { o = ++cnt; t[o] = t[p]; ins(t[o].rt, t[p].rt, 1, N, v.id, v.val); if (l == r) return ; int mid = (l + r) >> 1; if (v.nxt <= mid) insert(t[o].ls, t[p].ls, l, mid, v); else insert(t[o].rs, t[p].rs, mid + 1, r, v); } int que(int o, int l, int r, int ql, int qr) { if (!o) return 0; if (ql <= l && r <= qr) return It[o].mx; int mid = (l + r) >> 1; if (qr <= mid) return que(It[o].ls, l, mid, ql, qr); else if (ql > mid) return que(It[o].rs, mid + 1, r, ql, qr); else return max(que(It[o].ls, l, mid, ql, qr), que(It[o].rs, mid + 1, r, ql, qr)); } int query(int o, int l, int r, int pl, int pr, int ql, int qr) { if (!o) return 0; if (pl <= l && r <= pr) return que(t[o].rt, 1, N, ql, qr); int mid = (l + r) >> 1; if (pr <= mid) return query(t[o].ls, l, mid, pl, pr, ql, qr); else if (pl > mid) return query(t[o].rs, mid + 1, r, pl, pr, ql, qr); else return max(query(t[o].ls, l, mid, pl, pr, ql, qr), query(t[o].rs, mid + 1, r, pl, pr, ql, qr)); } set<int> s[MAX_N]; int ans = 0; int main () { N = gi(), M = gi(); for (int i = 1; i <= N; i++) s[i].insert(1), s[i].insert(N + 2); for (int i = 1; i <= N; i++) a[i].val = gi(), s[a[i].val].insert(i + 1), a[i].id = i; for (int i = 1; i <= N; i++) { set<int> :: iterator ite = s[a[i].val].find(i + 1); a[i].pre = *--ite, ++ite, a[i].nxt = *++ite; } sort(&a[1], &a[N + 1]); for (int i = 1, j = 1; i <= N + 2; i++) { rt[i] = rt[i - 1]; while (j <= N && a[j].pre == i) insert(rt[i], rt[i], 1, N + 2, a[j++]); } while (M--) { int l = gi(), r = gi(); l = (l + ans) % N + 1; r = (r + ans) % N + 1; if (r < l) swap(l, r); l++; r++; printf("%d\n", ans = query(rt[l - 1], 1, N + 2, r + 1, N + 2, l - 1, r - 1)); } return 0; }