Description
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?
Input
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
Output
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
Sample Input
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
Sample Output
4
4
3
4
HINT
对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
2016.3.2新加数据两组by Nano_Ape
Source
思路
带修莫队模板题。
PS:由于很SB的用了很多++和--的操作,导致代码难懂。。。下面给出一篇博客参考
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10005;
int n, m, Q, a[MAXN];
struct Query
{
int id, l, r, Time, ans;
Query () {}
Query(int _id, int _l, int _r, int _time)
{
id = _id; l = _l; r = _r; Time = _time;
ans = 0;
}
}q[MAXN];
struct Change
{
int pos, Old, New;
Change() {}
Change(int _pos, int _Old, int _New) { pos = _pos; Old = _Old; New = _New; }
}c[MAXN];
int block, l, r, T, ans, cnt[MAXN*100], pos[MAXN], now[MAXN];
bool cmp(Query A, Query B)
{
if (pos[A.l] != pos[B.l]) return A.l < B.l;
if (pos[A.r] != pos[B.r]) return A.r < B.r;
return A.Time < B.Time;
}
bool cmp_id(Query A, Query B){ return A.id < B.id; }
void update(int x, int d)
{
cnt[x] += d;
if (cnt[x] == 0 && d == -1) ans--;
if (cnt[x] == 1 && d == 1) ans++;
}
void change(int x, int d)
{
if (l <= x && x <= r)
{
update(d, 1),
update(a[x], -1);
}
a[x] = d;
}
int main()
{
scanf("%d%d", &n, &m);
block = pow(n, 2.0/3);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
now[i] = a[i];
pos[i] = (i-1)/block+1;
}
while (m--)
{
char op; int x, y; scanf(" %c %d%d", &op, &x, &y);
if (op == 'Q') q[Q++] = Query(Q, x, y, T);
if (op == 'R') c[++T] = Change(x, now[x], y), now[x] = y;
}
sort(q, q+Q, cmp);
l = 1, r = 0, T = 0, ans = 0;
for (int i = 0; i < Q; i++)
{
//++和--的位置和顺序一定不能错
while (T < q[i].Time) change(c[T].pos, c[++T].New);//T先++,然后传给两个参数
while (T > q[i].Time) change(c[T--].pos, c[T].Old);//先传给两个参数然后T--
while (l < q[i].l) update(a[l++], -1);
while (l > q[i].l) update(a[--l], 1);
while (r < q[i].r) update(a[++r], 1);
while (r > q[i].r) update(a[r--], -1);
q[i].ans = ans;
}
sort(q, q+Q, cmp_id);
for (int i = 0; i < Q; i++) printf("%d\n", q[i].ans);
return 0;
}
/*
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
*/