• [BJOI2019]删数


    首先,不难发现,第一个被删的数一定为 (n) 然后被删的数一定为 (n - S_n)(S_n)(n) 出现过的次数)。

    那么如果要一趟被删完当且仅当每个这样的过程都要接起来。

    可以发现这是一个极为抽象的过程,可以考虑将这个抽象问题具体化。

    可以想象一个二维平面,横坐标表示值域,纵坐标表示这个值域出现过的数,对于每个数 (i),连一条 ((i, 0) ightarrow (i, S_i)) 的线段。

    那么你可以发现,删掉 (n) 后删的数就是将 (x = n) 上的这条线段往左放倒后左端点所在的哪个点对应的数。

    不难发现对于任意一个数它放倒的区间都是 ([i - S_i, i])

    进一步可以发现,如果一个序列是能恰好删完的,当且仅当恰好完全覆盖了 ([0, n]) 上的所有位置。

    此时不难发现,原问题修改的下界应该至少是 ([0, n]) 中没有被覆盖的数量,显然的是,这个下界总是能达到的。

    那么不带修的情况直接差分区间覆盖即可,下面来考虑待修的情况。

    1. 支持单点修改,不难发现本质上是将 (a_p) 的放倒区间左边缩减 (1),将 (x) 的放倒区间左边增加 (1) 不难发现这是可以直接修改做到 (O(1)) 的。

    2. 支持整体 (+1/-1),不难发现本质上是将刚刚的覆盖区间整体平移,只需要记录一个变化量即可。但是,当放倒区间的右端点到 (n) 右侧以后,他是不能对覆盖产生贡献的。(因为至少要把这些数全部改成 (n) 以下)。所以这种情况下需要支持某个右端点跨过 (n) 时将之前的贡献消除,不难发现使用线段树进行区间加减即可。

    最后查询的时候只需要查询对应区间内 (0) 的数量,不难发现每个区间的最小值都不大于 (0),直接维护最小值数量即可。

    一些坑点

    • ( m pushup) 的时候一定不能直接返回左右儿子,因为此时会将左右儿子的懒标记一起返回。(因为这个调了一晚上
    #include <bits/stdc++.h>
    using namespace std;
    #define ls (p << 1)
    #define rs (p << 1 | 1)
    #define mid (l + r >> 1)
    #define rep(i, l, r) for (int i = l; i <= r; ++i)
    const int N = 6e5 + 5;
    struct tree { int min, cnt, tag;} ans, t[N << 2];
    int n, m, p, x, L, D, a[N], S[N];
    int read() {
        char c; int x = 0, f = 1;
        c = getchar();
        while (c > '9' || c < '0') { if(c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    tree chkmin(tree L, tree R) {
        if(L.min < R.min) return (tree){L.min, L.cnt, 0};
        else if(L.min > R.min) return (tree){R.min, R.cnt, 0};
        else return (tree){L.min, L.cnt + R.cnt, 0};
    }
    void lazy(int p, int l, int r, int k) {
        t[p].min += k, t[p].tag += k;
    }
    void down(int p, int l, int r) {
        if(!t[p].tag) return;
        lazy(ls, l, mid, t[p].tag), lazy(rs, mid + 1, r, t[p].tag);
        t[p].tag = 0;
    }
    void build(int p, int l, int r) {
        t[p].cnt = r - l + 1;
        if(l == r) return;
        build(ls, l, mid), build(rs, mid + 1, r);
    }
    void update(int p, int l, int r, int x, int y, int k) {
        if(x > y) return;
        if(l >= x && r <= y) { lazy(p, l, r, k); return;}
        down(p, l, r);
        if(mid >= x) update(ls, l, mid, x, y, k);
        if(mid < y) update(rs, mid + 1, r, x, y, k);
        t[p] = chkmin(t[ls], t[rs]);
    }
    tree query(int p, int l, int r, int x, int y) {
        if(l >= x && r <= y) return t[p];
        down(p, l, r);
        tree ans = (tree){n + 1, 0, 0};
        if(mid >= x) ans = chkmin(ans, query(ls, l, mid, x, y));
        if(mid < y) ans = chkmin(ans, query(rs, mid + 1, r, x, y));
        return ans; 
    }
    int main() {
        n = read(), m = read(), L = 2 * n + 2 * m;
        rep(i, 1, n) a[i] = read() + n + m, ++S[a[i]];
        build(1, 1, L);
        rep(i, n + m + 1, n * 2 + m) update(1, 1, L, i - S[i] + 1, i, 1);
        rep(i, 1, m) {
            p = read(), x = read();
            if(p) {
                x += n + m;
                if(a[p] + D <= n * 2 + m) update(1, 1, L, a[p] - S[a[p]] + 1, a[p] - S[a[p]] + 1, -1);
                --S[a[p]];
                ++S[x - D];
                update(1, 1, L, x - S[x - D] - D + 1, x - S[x - D] - D + 1, 1);
                a[p] = x - D; 
            }
            else {
                if(x == -1) {
                    --D;
                    if(S[n * 2 + m - D]) update(1, 1, L, n * 2 + m - D - S[n * 2 + m - D] + 1, n * 2 + m - D, 1);
                }
                else {
                    if(S[n * 2 + m - D]) update(1, 1, L, n * 2 + m - D - S[n * 2 + m - D] + 1, n * 2 + m - D, -1);
                    ++D;
                }
            }
            ans = query(1, 1, L, n + m - D + 1, n * 2 + m - D);
            printf("%d
    ", !ans.min ? ans.cnt : 0);
        }
        return 0;
    }
    
  • 相关阅读:
    STL之rb_tree的find函数
    Ruby对象、变量和常量
    Welcome to the Real World
    Git经常使用命令
    Android休眠唤醒机制简介(一)【转】
    DirectFB学习之移植到nuc972平台 标签: DirectFBlinux图形加速驱动【转】
    Buildroot构建指南——工具链【转】
    深入浅出
    android 添加一个按键键值【转】
    Android系统升级那些事儿【转】
  • 原文地址:https://www.cnblogs.com/Go7338395/p/13884740.html
Copyright © 2020-2023  润新知