传送门.
本来应该用数据结构大力解决这题,无非就是对于每一个点求一个next、last分别表示上一个和下一个和它相同的,然后变成了三维偏序问题。
然后随便想了个分块,考虑不仅对序列分块,还对值域分块。
设 s i , j , k s_{i,j,k} si,j,k表示序列中的第i块到第j块在值域第k块的出现次数为1的个数。
再维护个前缀和 p i , j p_{i,j} pi,j表示序列前i块在j的个数。
然后就可以快速确定答案在不在一个块里,如果在,进去暴力即可。
发现被卡常了,然后就要……
Code:
#pragma GCC optimize(2)
#include
#include
#include
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
using namespace std;
const int N = 1e5 + 5, M = 240, C = N / M + 5;
int n, m, a[N];
int l[N], r[N], bl[N];
int b[C][N], s[C][C][C], li[C], cnt[N];
int x, y, ans;
int main() {
scanf("%d %d", &n, &m);
fo(i, 1, n) {
bl[i] = bl[i - 1];
if(i % M == 1) r[bl[i]] = i - 1, l[++ bl[i]] = i;
} r[bl[n]] = n;
fo(i, 1, n) scanf("%d", &a[i]);
fo(i, 1, bl[n]) {
fo(j, 1, n) cnt[j] = 0;
fo(j, i, bl[n]) {
memcpy(s[i][j], s[i][j - 1], sizeof s[i][j]);
fo(k, l[j], r[j])
if(++ cnt[a[k]] == 1) s[i][j][bl[a[k]]] ++; else
s[i][j][bl[a[k]]] -= cnt[a[k]] == 2;
}
}
fo(i, 1, bl[n]) {
memcpy(b[i], b[i - 1], sizeof b[i]);
fo(j, l[i], r[i]) b[i][a[j]] ++;
}
fo(j, 1, n) cnt[j] = 0; fo(j, 1, bl[n]) li[j] = 0;
fo(ii, 1, m) {
scanf("%d %d", &x, &y);
x = (x + ans) % n + 1;
y = (y + ans) % n + 1;
if(x > y) swap(x, y);
ans = 0;
int p = bl[x] + 1, q = bl[y] - 1;
int tx, ty;
if(bl[x] == bl[y])
tx = y, ty = y + 1; else
tx = r[bl[x]], ty = l[bl[y]];
int ex = 0, ey = 0;
if(bl[x] != bl[y]) {
if(tx - x > M / 2) {
p --;
tx = l[bl[x]];
x --;
ex = 1;
}
if(y - ty > M / 2) {
q ++;
ty = r[bl[y]];
y ++;
ey = 1;
}
}
if(p > q) q = p - 1;
fo(i, 1, bl[n]) li[i] = s[p][q][i];
if(!ex) {
fo(i, x, tx) {
cnt[a[i]] ++; int w = b[q][a[i]] - b[p - 1][a[i]];
li[bl[a[i]]] += (cnt[a[i]] + w) == 1;
li[bl[a[i]]] -= (cnt[a[i]] + w) == 2;
}
} else {
fo(i, tx, x) {
cnt[a[i]] --; int w = b[q][a[i]] - b[p - 1][a[i]];
li[bl[a[i]]] += (cnt[a[i]] + w) == 1;
li[bl[a[i]]] -= (cnt[a[i]] + w) == 0;
}
}
if(!ey) {
fo(i, ty, y) {
cnt[a[i]] ++; int w = b[q][a[i]] - b[p - 1][a[i]];
li[bl[a[i]]] += (cnt[a[i]] + w) == 1;
li[bl[a[i]]] -= (cnt[a[i]] + w) == 2;
}
} else {
fo(i, y, ty) {
cnt[a[i]] --; int w = b[q][a[i]] - b[p - 1][a[i]];
li[bl[a[i]]] += (cnt[a[i]] + w) == 1;
li[bl[a[i]]] -= (cnt[a[i]] + w) == 0;
}
}
fd(i, bl[n], 1) if(li[i]) {
fd(j, r[i], l[i])
if(cnt[j] + b[q][j] - b[p - 1][j] == 1) {
ans = j; break;
}
break;
}
fo(i, 1, bl[n]) li[i] = 0;
if(!ex) fo(i, x, tx) cnt[a[i]] = 0; else fo(i, tx, x) cnt[a[i]] = 0;
if(!ey) fo(i, ty, y) cnt[a[i]] = 0; else fo(i, y, ty) cnt[a[i]] = 0;
printf("%d\n", ans);
}
}