今天心血来潮学习了一下主席树(可持久化线段树),于是就拿这题来练手了。发现其实还挺好写的,至少比之前写的树套树短多了。
PS:主席树虽然比较好写,速度也很快,但是内存实在是伤不起。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int N = 50005;
set <int> a[1000005];
typedef set<int>::iterator IT;
struct vertice {
int left, right, data;
} tree[N * 200];
int root[N], next[N], b[N];
int tot;
int n;
int lowbit(int x) { return x & -x; }
namespace Nsolve {
void new_vertice(int &k) {
k = ++tot;
}
void add(int &k, int m, int n, int x, int s) {
if (m > x || n < x) return ;
if (k == 0) new_vertice(k);
if (m == n) {
tree[k].data += s;
return ;
}
int mid = m + n >> 1;
add(tree[k].left, m, mid, x, s);
add(tree[k].right, mid + 1, n, x, s);
tree[k].data = 0;
if (tree[k].left) tree[k].data += tree[tree[k].left].data;
if (tree[k].right) tree[k].data += tree[tree[k].right].data;
}
void addpoint(int x, int y, int s) {
for (int j = x; j <= n; j += lowbit(j))
add(root[j], 0, n, y, s);
}
void modify(int x, int y) {
IT t1 = a[b[x]].upper_bound(x);
IT t2 = a[b[x]].lower_bound(x);
int t = 0;
if (t2 != a[b[x]].begin()) {
--t2;
t = *t2;
}
addpoint(x, t, -1);
if (t1 != a[b[x]].end()) {
addpoint(*t1, x, -1);
addpoint(*t1, t, 1);
}
a[b[x]].erase(x);
b[x] = y;
a[y].insert(x);
t1 = a[y].upper_bound(x);
t2 = a[y].lower_bound(x);
t = 0;
if (t2 != a[y].begin()) {
--t2;
t = *t2;
}
if (t1 != a[y].end()) {
addpoint(*t1, t, -1);
addpoint(*t1, x, 1);
}
addpoint(x, t, 1);
}
int query(int k, int m, int n, int l, int r) {
if (m > r || n < l) return 0;
if (m >= l && n <= r) return tree[k].data;
int mid = m + n >> 1;
return query(tree[k].left, m, mid, l, r) +
query(tree[k].right, mid + 1, n, l, r);
}
void solve(int n, int q) {
while (q--) {
int ch;
while (ch = getchar(), ch != 'M' && ch != 'Q');
if (ch == 'M') {
int x, y;
scanf("%d%d", &x, &y);
++x;
modify(x, y);
continue;
}
int ans = 0;
int l, r;
scanf("%d%d", &l, &r);
++l;
for (int i = r; i; i -= lowbit(i))
ans += query(root[i], 0, n, 0, l - 1);
for (int i = l - 1; i; i -= lowbit(i))
ans -= query(root[i], 0, n, 0, l - 1);
printf("%d\n", ans);
}
}
};
namespace Ninit {
void init(int n) {
for (int i = 1; i <= n; ++i) {
int x;
scanf("%d", &x);
a[x].insert(i);
IT it = a[x].lower_bound(i);
int t = 0;
if (it != a[x].begin()) {
--it;
t = *it;
}
b[i] = x;
Nsolve::addpoint(i, t, 1);
}
}
};
int main() {
int q;
scanf("%d%d", &n, &q);
Ninit::init(n);
Nsolve::solve(n, q);
return 0;
}