• 【CF-1436E】Complicated Computations(贪心+主席数求区间MEX)


    题目链接:https://codeforces.ml/contest/1436/problem/E

    题目大意

    给定一个序列,每次枚举一对 (l,r),能够得到 (MEX),对于整个序列的所有的 (l,r),求其所有的 (MEX) 数的 (MEX)

    花絮

    之前和WISH2LUCKY讨论了一个鬼畜的MEX问题,然后就让他做了区间MEX的模板题,然后7酱路过,就说起了这题。

    做这题之前补了牛客小米邀请赛第一场的E,也就拓宽了一些思路qwq。

    思路

    已知相同的一个数能将一个序列划分成不同的好几段,假定这个数是答案,例如一个数为 (1),序列为 ({2,1,3,4,1,4,6,7,1,3}),那么划分后能得到 ({2},{3,4},{4,6,7},{3})。如果这个数是不是答案,那么会是这些段的 (MEX)。如果对于所有裁剪出来的,都不是 (MEX),从小到大枚举,那就是答案了!

    那么如何证明是裁剪出来的一整段呢?这部分是口胡出来的,证明本当苦手

    因为如果是较小的数的话,会将裁剪后的进行进一步切分,所以 出现的 (MEX) 只会变小,因为枚举的数以及不在裁剪后的部分里面了,所以 (MEX) 只会更小,而更小的情况在枚举的时候就能判断掉了。

    AC代码

    板子很长,跑得挺快

    #include <bits/stdc++.h>
    
    #define SZ(x) (int)x.size()
    using namespace std;
    const int MAXN = 1e5 + 5;
    
    int bep;
    
    class HJT {
    public:
        struct node {
            int lson, rson, maxx;
        } T[MAXN * 70];
        int tol;
    #define ls T[rt].lson
    #define rs T[rt].rson
    
        inline void push_up(int rt) {
            T[rt].maxx = max(T[ls].maxx, T[rs].maxx);
        }
    
        int build(int l, int r) {
            int nrt = ++tol;
            int mid = (l + r) >> 1;
            T[nrt].lson = T[nrt].rson = 0;
            T[nrt].maxx = bep;
            if (l < r) {
                T[nrt].lson = build(l, mid);
                T[nrt].rson = build(mid + 1, r);
                push_up(nrt);
            }
            return nrt;
        }
    
        int update(int rt, int pos, int v, int be, int en) {
            int nrt = ++tol;
            if (be == en) {
                T[nrt].maxx = v;
                return nrt;
            }
            int mid = (be + en) >> 1;
            if (pos <= mid) {
                T[nrt].lson = update(T[rt].lson, pos, v, be, mid);
                T[nrt].rson = T[rt].rson;
            } else {
                T[nrt].lson = T[rt].lson;
                T[nrt].rson = update(T[rt].rson, pos, v, mid + 1, en);
            }
            push_up(nrt);
            return nrt;
        }
    
        int query(int rt, int R, int be, int en) {
            if (be == en) return be;
            int ans = -1;
            int mid = (be + en) >> 1;
            if (T[ls].maxx > R) ans = query(T[rt].lson, R, be, mid);
            if (ans == -1 && T[rs].maxx > R) ans = query(T[rt].rson, R, mid + 1, en);
            return ans;
        }
    } tree;
    
    int root[MAXN];
    int a[MAXN];
    
    vector<int> vec[MAXN];
    
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        bep = n + 1;
        root[n + 1] = tree.build(1, n+1);
        for (int i = n; i >= 1; i--) {
            int x = a[i];
            root[i] = tree.update(root[i + 1], x, i, 1, n+1);
        }
    
        for (int i = 1; i <= n; i++) {
            vec[a[i]].push_back(i);
        }
    
        for (int i = 1; i <= n+1; i++) {
            int flag = 0;
            if (SZ(vec[i]) == 0) {
                printf("%d", i+1);
                return 0;
            }
            for (int j = 0; j <= SZ(vec[i]); j++) {
                int l, r;
                if (j == 0) {
                    l = 1, r = vec[i][j] - 1;
                } else if (j == SZ(vec[i])) {
                    l = vec[i][j - 1] + 1, r = n;
                } else {
                    l = vec[i][j - 1] + 1, r = vec[i][j] - 1;
                }
                if (l > r) continue;
                else {
                    int tmp = tree.query(root[l], r, 1, n+1);
                    if (tmp == -1) continue;
                    else {
                        if (tmp == i) {
                            flag = 1;
                        }
                    }
                }
            }
            if (!flag) {
                printf("%d
    ", i);
                return 0;
            }
        }
    }
    
  • 相关阅读:
    LinQ表达式的一点点总结(二)select中新建对象
    给自己的博客添加分享到功能
    职场日记2上班第一天
    清楚屏幕右侧变化的数据Application.Current.Host.Settings.EnableFrameRateCounter = true;
    基于委托的异步
    C#中的装箱与拆箱
    关于java的初始化问题
    StreamReader类以及其方法ReadLine,Read,ReadToEnd的分析
    WP7的控件开发入门(二)
    单元测试的阶段性总结
  • 原文地址:https://www.cnblogs.com/tudouuuuu/p/14010275.html
Copyright © 2020-2023  润新知