BZOJ ~ 2120 ~ 数颜色(带修莫队)

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的用了很多++和--的操作,导致代码难懂。。。下面给出一篇博客参考

关于c语言和c++中的函数参数的执行顺序的问题

#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
*/

猜你喜欢

转载自blog.csdn.net/ZscDst/article/details/81134425