【BZOJ3489】A simple rmq problem
【BZOJ3489】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;
}