UVa12345 Dynamic len(set(a[L:R])) <带修莫队>
Dynamic len(set(a[L:R]))
In python, we can use len(start(a[L:R])) to calculate the number of distinct values of elements a[L],
a[L + 1], . . . , a[R ? 1].
Here are some interactive examples that may help you understand how it is done. Remember that
the indices of python lists start from 0.
a=[1,2,1,3,2,1,4]
print a[1:6]
[2, 1, 3, 2, 1]
print set(a[1:6])
set([1, 2, 3])
len(set(a[1:6]))
3
a[3]=2
len(set(a[1:6]))
2
print len(set(a[3:5]))
1
Your task is to simulate this process.Input
There will be only one test case. The first line contains two integers n and m (1 ≤ n; m ≤ 50; 000).
The next line contains the original list.
All the integers are between 1 and 1,000,000 (inclusive). The next m lines contain the statements
that you need to execute.
A line formatted as ‘M x y’ (1 ≤ y ≤ 1; 000; 000) means \a[x] = y", and a line formatted as ‘Q x
y’ means \print len(set(a[x : y]))".
It is guaranteed that the statements will not cause \index out of range" error.
Output
Print the simulated result, one line for each query.Sample Input
7 4
1 2 1 3 2 1 4
Q 1 6
M 3 2
Q 1 6
Q 3 5
Sample Output
3
2
1标签:带修莫队
题目大意:给出一个长为n的序列,有m个操作,分为两类:1. $Q a b$ 询问此序列a~b位间有多少种不同数;2. $M a b$ 将第a位改为b。
本题数据范围只有五万,一看就是带根号的算法,可以$O(n\sqrt{n})$莫队水过。
我们发现Q操作是标准莫队,但M操作是修改,因而需用带修莫队。
带修莫队即在普通莫队的双指针种再加一个指针,指向时间。对于离线后询问建的扩展,如果是同一时间,就直接移动双指针;如果是不同时间,就先暴力移动时间指针,然后再移双指针即可。
暴力出奇迹~~~附上AC代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #define MAX_N 50000 #define MAX_C 1000000 using namespace std; int n, m, tmp, col[MAX_N+5]; int cnt[MAX_C+5], pos[MAX_N+5], lst[MAX_N+5], ans[MAX_N+5]; bool mark[MAX_N+5]; struct Modify {int pos, x, pre;} M[MAX_N+5]; struct Query {int l, r, id, ts;} Q[MAX_N+5]; bool cmp(const Query &a, const Query &b) { return pos[a.l] < pos[b.l] || (pos[a.l] == pos[b.l] && pos[a.r] < pos[b.r]) || (pos[a.l] == pos[b.l] && pos[a.r] == pos[b.r] && a.ts < b.ts); } void add(int x) { if (mark[x]) { cnt[col[x]]--; if (!cnt[col[x]]) tmp--; } else { if (!cnt[col[x]]) tmp++; cnt[col[x]]++; } mark[x] ^= 1; } void change(int x, int y) { if (mark[x]) add(x), col[x] = y, add(x); else col[x] = y; } int main() { scanf("%d%d", &n, &m); int magic = (int)(sqrt((double)n+0.5)); int tot = 0, ind = 0; for (int i = 1; i <= n; i++) scanf("%d", &col[i]), lst[i] = col[i], pos[i] = i/magic; for (int i = 1; i <= m; i++) { char opt[2]; int x, y; scanf("%s%d%d", opt, &x, &y); x++; if (opt[0] == 'Q') { Q[++tot].id = tot; Q[tot].l = x, Q[tot].r = y, Q[tot].ts = ind; } else { M[++ind].pos = x, M[ind].x = y, M[ind].pre = lst[x]; lst[x] = y; } } sort(Q+1, Q+tot+1, cmp); int now = 0, l = 1, r = 0; for (int i = 1; i <= tot; i++) { if (now < Q[i].ts) for (int j = now+1; j <= Q[i].ts; j++) change(M[j].pos, M[j].x); if (now > Q[i].ts) for (int j = now; j > Q[i].ts; j--) change(M[j].pos, M[j].pre); if (l > Q[i].l) for (int j = l-1; j >= Q[i].l; j--) add(j); if (r < Q[i].r) for (int j = r+1; j <= Q[i].r; j++) add(j); if (l < Q[i].l) for (int j = l; j < Q[i].l; j++) add(j); if (r > Q[i].r) for (int j = r; j > Q[i].r; j--) add(j); now = Q[i].ts, l = Q[i].l, r = Q[i].r; ans[Q[i].id] = tmp; } for (int i = 1; i <= tot; i++) printf("%d\n", ans[i]); return 0; }