莫队算法,也可以用主席树,好像还能用树状数组乱搞?
#include <iostream>
#include <cmath>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 4e5 + 10;
int a[N];
int n, q, L;
struct Interval {
int l, r, id, index, num, flag;
bool operator < (const Interval& p) const {
if (id != p.id) return id < p.id;
return (id & 1) ? r < p.r : r > p.r;
}
} I[N];
bool cmp(const Interval &a, const Interval &b) {
return a.index < b.index;
}
int mp[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> q;
L = sqrt(2*n);
for(int i = 1; i <= n; i++) cin >> a[i];
vector<int> vals;
for (int i = 1; i <= n; i++) vals.push_back(a[i]);
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
int cc = vals.size();
for (int i = 1; i <= n; i++) {
a[i] = lower_bound(vals.begin(), vals.end(), a[i]) - vals.begin() + 1;
a[i + n] = a[i];
}
int l = 0, r = 0;
for(int i = 1; i <= q; i++) {
char ch; int x; cin >> ch >> x;
if(x >= n) {
I[i].flag = true;
if(ch == 'L') l = (l + x) % n;
else r = (r + x) % n;
continue;
}
else I[i].flag = false;
if(ch== 'L') {
I[i].l = (l + 1) % n; if(!I[i].l) I[i].l = n;
I[i].r = (I[i].l + x - 1);
l = (l + x) % n;
// cout << I[i].l << " L " << I[i].r << endl;
}
else {
I[i].r = ((n - r) % n + n) % n + n;
I[i].l = (I[i].r - x + 1);
r = (r + x) % n;
// cout << I[i].l << " R " << I[i].r << endl;
}
}
for(int i = 1; i <= q; i++) {
I[i].id = I[i].l / L;
I[i].index = i;
}
sort(I + 1, I + q + 1);
// for(int i = 1; i <= q; i++) cout << I[i].l << ' ' << I[i].r << " " << I[i].flag << endl;
int cnt = 0, ok = false;
int lst = -1;
for(int i = 1; i <= q; i++) {
if(I[i].flag) continue;
// if(I[i].l > I[i].r) cout << " ??? " << endl;
if(!ok) { // I[i].id != I[lst].id
ok = true;
memset(mp, 0, sizeof(mp));
cnt = 0;
for(int j = I[i].l; j <= I[i].r; j++) {
if(!mp[a[j]]) cnt++;
mp[a[j]]++;
}
I[i].num = cnt;
}
else {
for(int j = I[lst].r; j > I[i].r; j--) {
if(--mp[a[j]] == 0) {
cnt--;
}
}
for(int j = I[lst].r + 1; j <= I[i].r; j++) {
if(!mp[a[j]]) cnt++;
mp[a[j]]++;
}
for(int j = I[lst].l; j < I[i].l; j++) {
if(--mp[a[j]] == 0) {
cnt--;
}
}
for(int j = I[lst].l - 1; j >= I[i].l; j--) {
if(!mp[a[j]]) cnt++;
mp[a[j]]++;
}
I[i].num = cnt;
}
lst = i;
}
sort(I + 1, I + q + 1, cmp);
// for(int i = 1; i <= q; i++) cout << I[i].l << ' ' << I[i].r << endl;
for(int i = 1; i <= q; i++) {
if(I[i].flag) printf("%d\n", cc);
else printf("%d\n", I[i].num);
}
}
// 64 位输出请用 printf("%lld")
// 10 10
// 4 5 3 10 4 7 10 5 4 8
// L 8
// R 4
// L 3
// L 4
// L 1
// L 3
// R 4
// R 3
// L 10
// L 10