洛谷 P1903 [国家集训队]数颜色 / 维护队列 题解

\(Description\)

Luogu传送门

\(Solution\)

带修莫队板子题。

就是再多开一维时间轴,把每次修改修改前的颜色和修改后的颜色都记录下来。

离线处理。

枚举操作时,类似于普通的莫队,while(操作时间) 看看是该插入还是删除,然后直接修改就完了。

贴下代码吧,直接看代码比较好理解。

\(Code\)

#include <bits/stdc++.h>
#define get_B(x) x / B

using namespace std;

namespace IO{
    inline int read(){
        int x = 0;
        char ch = getchar();
        while(!isdigit(ch)) ch = getchar();
        while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
        return x;
    }

    template <typename T> inline void write(T x){
        if(x > 9) write(x / 10);
        putchar(x % 10 + '0');
    }
}
using namespace IO;

const int N = 2e5 + 10;
const int M = 1e6 + 10;
int n, m, B, res;
int c[N], col[N];
char op[3];
struct Upd{
    int pos, col, pre;
}p[N];
struct Qry{
    int l, r, t, pos;
    friend bool operator < (Qry a, Qry b){
        if(get_B(a.l) != get_B(b.l)) return get_B(a.l) < get_B(b.l);
        return get_B(a.r) != get_B(b.r) ? get_B(a.r) < get_B(b.r) : a.t < b.t;
    }
}q[N];
int tp, tq;
int vis[M], ans[N];

int main(){
    n = read(), m = read();
    for(int i = 1; i <= n; ++i) col[i] = c[i] = read();
    for(int i = 1; i <= m; ++i){
        scanf("%s", op);
        int x = read(), y = read();
        if(op[0] == 'R') p[++tp] = (Upd){x, y, c[x]}, c[x] = y;
        else q[++tq] = (Qry){x, y, tp, tq};
    }
    if(!tq) return 0;
    B = pow(n, 0.7);
    sort(q + 1, q + 1 + tq);
    int l = 1, r = 0, t = 0;
    for(int i = 1; i <= tq; ++i){
        while(l > q[i].l) res += !vis[col[--l]]++;
        while(l < q[i].l) res -= !--vis[col[l++]];
        while(r < q[i].r) res += !vis[col[++r]]++;
        while(r > q[i].r) res -= !--vis[col[r--]];
        while(t > q[i].t){
            int x = p[t].pos;
            if(l <= x && x <= r) res -= !--vis[col[x]];
            col[x] = p[t--].pre;
            if(l <= x && x <= r) res += !vis[col[x]]++;
        }
        while(t < q[i].t){
            int x = p[++t].pos;
            if(l <= x && x <= r) res -= !--vis[col[x]];
            col[x] = p[t].col;
            if(l <= x && x <= r) res += !vis[col[x]]++;
        }
        ans[q[i].pos] = res;
    }
    for(int i = 1; i <= tq; ++i) write(ans[i]), puts("");
    return 0;
}

\[\_EOF\_ \]

上一篇:[DFS]棋盘问题-POJ 1321


下一篇:排序算法【2】——快速排序