CF940F Machine Learning 题解 带修莫队

题目链接:https://www.luogu.com.cn/problem/CF940F

带修莫队 模板题。

求 mex 的部分可以暴力。逻辑完全参考自 ouuan 大佬的博客

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;

int n, M, Q, blo, a[maxn], ans[maxn], idx1, idx2;
unordered_map<int, int> mp;

int cnt1[maxn*2], cnt2[maxn];

struct Query {
    int id, l, r, t;
} query[maxn];

struct Event {
    int p, c;
} event[maxn];

void add(int c) {
    cnt2[ cnt1[c] ]--;
    cnt1[c]++;
    cnt2[ cnt1[c] ]++;
}

void del(int c) {
    cnt2[ cnt1[c] ]--;
    cnt1[c]--;
    cnt2[ cnt1[c] ]++;
}

int mex() {
    for (int i = 1; ; i++)
        if (!cnt2[i])
            return i;
}

void lsh() {
    vector<int> v;
    for (int i = 1; i <= n; i++) v.push_back(a[i]);
    for (int i = 1; i <= idx2; i++) v.push_back(event[i].c);
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    for (int i = 1; i <= n; i++) a[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
    for (int i = 1; i <= idx2; i++) event[i].c = lower_bound(v.begin(), v.end(), event[i].c) - v.begin() + 1;
}

int main() {
    scanf("%d%d", &n, &Q);
    M = sqrt(n * 2) + 5;
    blo = pow(n, 2.0/3);
    for (int i = 1; i <= n; i++)
        scanf("%d", a+i);
    for (int i = 0; i < Q; i++) {
        int op;
        scanf("%d", &op);
        if (op == 1) { // 1 l r
            int l, r;
            scanf("%d%d", &l, &r);
            idx1++;
            query[idx1] = {idx1, l, r, idx2};
        }
        else { // 2 p c
            int p, c;
            scanf("%d%d", &p, &c);
            event[++idx2] = {p, c};
        }
    }

    lsh(); // 离散化

    sort(query+1, query+idx1+1, [](auto a, auto b) {

        if (a.l / blo != b.l / blo)
            return a.l < b.l;
        if (a.r / blo != b.r / blo)
            return a.r < b.r;
        return a.t < b.t;

      });
    for (int i = 1, l = 1, r = 0, t = 0; i <= idx1; i++) {
        while (l < query[i].l) del(a[l++]);
        while (l > query[i].l) add(a[--l]);
        while (r < query[i].r) add(a[++r]);
        while (r > query[i].r) del(a[r--]);
        for (; t < query[i].t; t++) {
            auto [p, c] = event[t+1];
            int x = a[p];
            if (p >= l && p <= r) {
                del(x);
                add(c);
            }
            a[p] = c;
            event[t+1].c = x;
        }
        for (; t > query[i].t; t--) {
            auto [p, c] = event[t];
            int x = a[p];
            if (p >= l && p <= r) {
                del(x);
                add(c);
            }
            a[p] = c;
            event[t].c = x;
        }
        ans[ query[i].id ] = mex();
    }

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

    return 0;
}
posted @ 2026-03-04 17:20  quanjun  阅读(1)  评论(0)    收藏  举报