墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:
1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。
2、 R P Col 把第P支画笔替换为颜色Col。
没有修改操作就是直接上莫队即可
有了修改操作我们就引入一个时间戳,对于一个询问,就记录一下它前面有多少个修改
在莫队过程中进行修改即可
#include
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define N 150005
using namespace std;
typedef long long ll;
struct Node {
int l, r, id, cp;
}q1[N];
struct Code {
int id, x;
}q2[N];
int beln[N], ans[N], cnt[N*7], a[N], n, m, now, tot1, tot2;
void read(int &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = - 1; s = getchar(); }
while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
x = x * f;
}
bool cmp(Node aa, Node bb) {
return (beln[aa.l] == beln[bb.l]) ? ((beln[aa.r] == beln[bb.r] ? aa.cp < bb.cp : beln[aa.r] < beln[bb.r])) : beln[aa.l] < beln[bb.l];
}
void add(int x) {
if (cnt[x] == 0) ++now; ++cnt[x];
}
void del(int x) {
if (cnt[x] == 1) --now; --cnt[x];
}
void write(int x) {
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int main() {
read(n); read(m);
int siz = pow(n, 2.0 / 3.0);
rep(i, 1, ceil((double)n / siz))
rep(j, (i - 1) * siz + 1, i * siz) beln[j] = i;
rep(i, 1, n) read(a[i]);
char opt[5];
rep(i, 1, m) {
scanf("%s", opt);
if (opt[0] == 'Q') ++tot1, read(q1[tot1].l), read(q1[tot1].r), q1[tot1].id = tot1, q1[tot1].cp = tot2;
else ++tot2, read(q2[tot2].id), read(q2[tot2].x);
}
sort(q1 + 1, q1 + tot1 + 1, cmp);
int l = 1, r = 0, z = 0;
rep(i, 1, tot1) {
while (l < q1[i].l) del(a[l]), l++;
while (l > q1[i].l) l--, add(a[l]);
while (r < q1[i].r) r++, add(a[r]);
while (r > q1[i].r) del(a[r]), r--;
while (z < q1[i].cp) {
++z;
if (q1[i].l <= q2[z].id && q2[z].id <= q1[i].r) del(a[q2[z].id]), add(q2[z].x);
swap(a[q2[z].id], q2[z].x);
}
while (z > q1[i].cp) {
if (q1[i].l <= q2[z].id && q2[z].id <= q1[i].r) del(a[q2[z].id]), add(q2[z].x);
swap(a[q2[z].id], q2[z].x);
--z;
}
ans[q1[i].id] = now;
}
rep(i, 1, tot1) write(ans[i]), printf("\n");
return 0;
}