【题目描述】

给定颜色序列,每次询问某个区间 $[l, r]$ 内,不同颜色的种数,要求支持单点修改颜色。

【题目链接】

BZOJ 2120 数颜色

【解题思路】

序列上带修改的莫队,详见 莫队算法 - 学习笔记

【AC代码】

#include <cstdio>
#include <algorithm>
#include <cmath>

const int MAXN = 10000;
const int MAXM = 10000;
const int MAXC = 1000000;

int n, m;
int qcnt, mcnt;
int color[MAXN];
int ans[MAXM];

struct Modification{
    int pos, color;
} modifications[MAXM];

int blockSize;

struct Query{
    int l, r, time;
    int id;

    inline friend bool operator<(const Query &a, const Query &b){
        if(a.l / blockSize != b.l / blockSize) return a.l / blockSize < b.l / blockSize;
        else if (a.r / blockSize != b.r / blockSize) return a.r / blockSize < b.r / blockSize;
        else return a.time < b.time;
    }
} querys[MAXM];

int l, r, currAns, currTime;
bool in[MAXN];
int buc[MAXC + 1];

void flip(int x){
    in[x] ^= 1;

    if(in[x]){
        if(++buc[ color[x] ] == 1) currAns++;
    } else{
        if(--buc[ color[x] ] == 0) currAns--;
    }
}

void flipModification(int x){
    Modification *o = modifications + x;

    if(l <= o->pos && o->pos <= r) flip(o->pos);
    std::swap(color[o->pos], o->color);
    if(l <= o->pos && o->pos <= r) flip(o->pos);
}

void solve(){
    blockSize = static_cast<int>(std::ceil(std::pow(n, 2.0 / 3.0)) + 1e-6);
    std::sort(querys, querys + qcnt);

    l = 0, r = 0, currTime = 0, flip(0);
    for(Query *q = querys; q != querys + qcnt; q++){
        while(currTime < q->time) flipModification(currTime++);
        while(currTime > q->time) flipModification(--currTime);

        while(l > q->l) flip(--l);
        while(r < q->r) flip(++r);
        while(l < q->l) flip(l++);
        while(r > q->r) flip(r--);

        ans[q->id] = currAns;
    }
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++) scanf("%d", color + i);

    qcnt = 0, mcnt = 0;
    for(int i = 0; i < m; i++){
        char ch;
        do ch = getchar(); while(ch != 'Q' && ch != 'R');

        if(ch == 'Q'){
            Query *q = querys + qcnt;

            scanf("%d%d", &q->l, &q->r), q->l--, q->r--;
            q->id = qcnt, q->time = mcnt;

            qcnt++;
        } else{
            Modification *o = modifications + mcnt;

            scanf("%d%d", &o->pos, &o->color), o->pos--;

            mcnt++;
        }
    }

    solve();

    for(int i = 0; i < qcnt; i++) printf("%d\n", ans[i]);

    return 0;
}

就是这样咯~