zoukankan      html  css  js  c++  java
  • Codeforces 1083C Max Mex 线段树 (看题解)

    Max Mex

    感觉好脑洞的一道题啊。

    用0 - n - 1的值建线段树, 每个区间维护 l - r 能否在一条路径上, 保存两个端点。

    感觉我的第一思路是二分答案, 然后判断那些点是否在一条路径上, 没想到这两条路径也能合并, 这样就能用线段树维护了。

    合并两条路径枚举合并之后的两端点, 暴力判。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;}
    
    const int LOG = 18;
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
    int n, q, p[N], d[N], a[N];
    int in[N], ot[N], idx;
    
    vector<int> G[N];
    int pa[N][LOG], depth[N];
    
    void dfs(int u, int fa) {
        depth[u] = depth[fa] + 1;
        pa[u][0] = fa;
        in[u] = ++idx;
        for(int i = 1; i < LOG; i++) {
            pa[u][i] = pa[pa[u][i - 1]][i - 1];
        }
        for(auto &v : G[u]) {
            dfs(v, u);
        }
        ot[u] = idx;
    }
    
    int getLca(int u, int v) {
        if(depth[u] < depth[v]) swap(u, v);
        int dis = depth[u] - depth[v];
        for(int i = LOG - 1; i >= 0; i--) {
            if(dis >> i & 1) {
                u = pa[u][i];
            }
        }
        if(u == v) return u;
        for(int i = LOG - 1; i >= 0; i--) {
            if(pa[u][i] != pa[v][i]) {
                u = pa[u][i];
                v = pa[v][i];
            }
        }
        return pa[u][0];
    }
    
    inline bool isAnc(int u, int v) {
        return in[u] <= in[v] && ot[v] <= ot[u];
    }
    
    inline bool onPath(int w, int u, int v) {
        int lca = getLca(u, v);
        if(isAnc(w, u) && isAnc(lca, w)) return true;
        if(isAnc(w, v) && isAnc(lca, w)) return true;
        return false;
    }
    
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    struct info {
        int u, v;
    };
    
    int id[4];
    
    info operator + (info A, info B) {
        if(A.u == -1 || B.u == -1) return info{-1, -1};
        if(A.u == 0) return B;
        if(B.u == 0) return A;
        id[0] = A.u; id[1] = A.v;
        id[2] = B.u; id[3] = B.v;
        for(int i = 0; i < 4; i++) {
            for(int j = i + 1; j < 4; j++) {
                bool can = true;
                for(int k = 0; k < 4; k++) {
                    if(k != i && k != j) {
                        if(!onPath(id[k], id[i], id[j])) {
                            can = false;
                            break;
                        }
                    }
                }
                if(can) {
                    return info{id[i], id[j]};
                }
            }
        }
        return info{-1, -1};
    }
    
    struct SegmentTree {
        info a[N << 2];
        void build(int l, int r, int rt) {
            if(l == r) {
                a[rt].u = ::a[l];
                a[rt].v = ::a[l];
                return;
            }
            int mid = l + r >> 1;
            build(lson); build(rson);
            a[rt] = a[rt << 1] + a[rt << 1 | 1];
        }
        void update(int p, int v, int l, int r, int rt) {
            if(l == r) {
                a[rt].u = v;
                a[rt].v = v;
                return;
            }
            int mid = l + r >> 1;
            if(p <= mid) update(p, v, lson);
            else update(p, v, rson);
            a[rt] = a[rt << 1] + a[rt << 1 | 1];
        }
        void query(info &ret, int &ans, int l, int r, int rt) {
            if(l == r) return;
            int mid = l + r >> 1;
            info tmp = ret + a[rt << 1];
            if(tmp.u != -1) {
                ret = tmp;
                ans += mid - l + 1;
                query(ret, ans, rson);
            }
            else {
                query(ret, ans, lson);
            }
        }
    } Tree;
    
    int main() {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &p[i]);
            p[i]++;
            a[p[i]] = i;
        }
        for(int i = 2; i <= n; i++) {
            scanf("%d", &d[i]);
            G[d[i]].push_back(i);
        }
    
        dfs(1, 0);
        Tree.build(1, n , 1);
    
        scanf("%d", &q);
        while(q--) {
            int t;
            scanf("%d", &t);
            if(t == 1) {
                int x, y;
                scanf("%d%d", &x, &y);
                swap(p[x], p[y]);
                a[p[x]] = x;
                a[p[y]] = y;
                Tree.update(p[x], x, 1, n, 1);
                Tree.update(p[y], y, 1, n, 1);
            }
            else {
                if(Tree.a[1].u != -1) {
                    printf("%d
    ", n);
                }
                else {
                    info ret = info{0, 0};
                    int ans = 0;
                    Tree.query(ret, ans, 1, n, 1);
                    printf("%d
    ", ans);
                }
            }
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    20155313 杨瀚 《网络对抗技术》实验九 Web安全基础
    20155313 杨瀚 《网络对抗技术》实验八 Web基础
    20155313 杨瀚 《网络对抗技术》实验七 网络欺诈防范
    20155313 杨瀚 《网络对抗技术》实验六 信息搜集与漏洞扫描
    20155313 杨瀚 《网络对抗技术》实验五 MSF基础应用
    20155313 杨瀚 《网络对抗技术》实验四 恶意代码分析
    20155313 杨瀚 《网络对抗技术》实验三 免杀原理与实践
    20155313 杨瀚 《网络对抗技术》实验二 后门原理与实践
    20155313 杨瀚 《网络对抗技术》实验一 PC平台逆向破解(5)M
    20155313 2017-2018-1 《信息安全系统设计基础》课程总结
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11169228.html
Copyright © 2011-2022 走看看