zoukankan      html  css  js  c++  java
  • Codeforces 1062 E

    E - Company

    思路:

    首先,求出每个点的dfs序

    然后求一些点的公共lca, 就是求lca(u, v), 其中u是dfs序最大的点, v是dfs序最小的大点

    证明: 假设o是这些点的公共lca, in[o]是o的入时间戳, out[o]是o的出时间戳, 

    那么对于任意一点x, in[o] <= in[v] <= in[x] <= in[u] <= out[o]

    所以o是x的祖先

    所以o是这些点的公共lca

    所以只要求出每段区间的dfs序最大的和最小的, 删除的要么是最大的, 要么是最小的

    可以删除后分成两段区间来考虑或者再求一下次大的和次小的来考虑

    求次大次小可以用运算符重载写线段树, 要方便很多

    代码:

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize(4)
    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define pi acos(-1.0)
    #define LL long long
    //#define mp make_pair
    #define pb push_back
    #define ls rt<<1, l, m
    #define rs rt<<1|1, m+1, r
    #define ULL unsigned LL
    #define pll pair<LL, LL>
    #define pli pair<LL, int>
    #define pii pair<int, int>
    #define piii pair<pii, int>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
    //head
    
    const int N = 1e5 + 5;
    vector<int> g[N];
    int anc[N][20], deep[N], dfn[N], tot = 0;
    struct node {
        int mx, mn, _mx, _mn;
        node operator ^ (const node & rhs) {
            node res = rhs;
            if(dfn[mx] >= dfn[res.mx]) {
                res._mx = res.mx;
                res.mx = mx;
            }
            else if(dfn[mx] > dfn[res._mx]) {
                res._mx = mx;
            }
    
            if(dfn[mn] <= dfn[res.mn]) {
                res._mn = res.mn;
                res.mn = mn;
            }
            else if(dfn[mn] < dfn[res._mn]) {
                res._mn = mn;
            }
    
            if(dfn[_mx] >= dfn[res.mx]) {
                res._mx = res.mx;
                res.mx = _mx;
            }
            else if(dfn[_mx] > dfn[res._mx]) {
                res._mx = _mx;
            }
    
            if(dfn[_mn] <= dfn[res.mn]) {
                res._mn = res.mn;
                res.mn = _mn;
            }
            else if(dfn[_mn] < dfn[res._mn]) {
                res._mn = _mn;
            }
            return res;
        }
    }tree[N<<2];
    void dfs(int u, int o) {
        anc[u][0] = o;
        for (int i = 1; i < 20; i++) anc[u][i] = anc[anc[u][i-1]][i-1];
        deep[u] = deep[o] + 1;
        dfn[u] = ++tot;
        for (int v : g[u]) {
            if(v != o) {
                dfs(v, u);
            }
        }
    }
    int lca(int u, int v) {
        if(deep[u] < deep[v]) swap(u, v);
        for (int i = 19; i >= 0; i--) if(deep[anc[u][i]] >= deep[v]) u = anc[u][i];
        if(u == v) return u;
        for (int i = 19; i >= 0; i--) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i];
        return anc[u][0];
    }
    void push_up(int rt) {
        tree[rt] = tree[rt<<1] ^ tree[rt<<1|1];
    }
    void build(int rt, int l, int r) {
        if(l == r) {
            tree[rt] = node{l, l, 0, 100001};
            return ;
        }
        int m = l+r >> 1;
        build(ls);
        build(rs);
        push_up(rt);
    }
    node query(int L, int R, int rt, int l, int r) {
        if(L <= l && r <= R) return tree[rt];
        int m = l+r >> 1;
        node res = {0, 0, 0, 0};
        if(L <= m) res = query(L, R, ls);
        if(R > m) {
            if(res.mn == 0) res = query(L, R, rs);
            else res = res ^ query(L, R, rs);
        }
        return res;
    }
    int main() {
        int n, p, q, l, r;
        scanf("%d %d", &n, &q);
        for (int i = 2; i <= n; i++) {
            scanf("%d", &p);
            g[p].pb(i);
        }
        dfs(1, 1);
        dfn[100001] = 100001;
        build(1, 1, n);
        for (int i = 1; i <= q; i++) {
            scanf("%d %d", &l, &r);
            node tmp = query(l, r, 1, 1, n);
            int l1 = lca(tmp.mx, tmp._mn), l2 = lca(tmp._mx, tmp.mn);
    //        cout << tmp.mx << " " << tmp._mx << " " << tmp.mn << " " << tmp._mn << endl;
    //        cout << dfn[tmp.mx] << " " << dfn[tmp._mx] << " " << dfn[tmp.mn] << " " << dfn[tmp._mn] << endl;
    //        cout << l1 << " " << l2 << endl;
            if(deep[l1] < deep[l2]) printf("%d %d
    ", tmp.mx, deep[l2]-1);
            else printf("%d %d
    ", tmp.mn, deep[l1]-1);
        }
        return 0;
    }
  • 相关阅读:
    【CI】系列一:总体环境规划
    【原】Ubuntu下使用teamviewer
    [Android] android:visibility属性应用
    Android 软键盘
    android EditText inputType 及 android:imeOptions=”actionDone”
    【Android】The application has stopped unexpectedly.Please try again.
    【IntelliJ IDEA 12使用】导入外部包
    [转载]Android开发者必须深入学习的10个应用开源项目
    【android相关】【问题解决】R.java文件丢失
    1月1日起,我市交通事故快速理赔上限提高至1万元!
  • 原文地址:https://www.cnblogs.com/widsom/p/9969435.html
Copyright © 2011-2022 走看看