zoukankan      html  css  js  c++  java
  • [CF1062E] Company

    题意

    Here

    思考

    最重要的问题在于,我们删去哪个点后,剩下点的公共 (LCA) 深度最大,即如何确定这个点。我们感性的观察和理性的分析之后,发现和点的 (dfn) 序有关系,要么删去当前区间点 (dfn) 最大的,要么删最小的。

    如果得出上面那个结论就好办了,拿个线段树维护区间 (dfn) 的最大和最小值,选择是删 (dfn) 最大的点还是最小的点即可。

    代码

    #include<bits/stdc++.h>
    #define ls(pos) pos << 1
    #define rs(pos) pos << 1 | 1
    using namespace std;
    const int N = 100010;
    const int M = 100010;
    struct node{
        int nxt, to;
    }edge[M << 1];
    int head[N], num;
    void build(int from, int to){
        edge[++num].nxt = head[from];
        edge[num].to = to;
        head[from] = num;
    }
    int dfn[N], cnt, f[N][20], rev[N], d[N], n, q;
    namespace Seg{
        int Max[N << 2], Min[N << 2];
        void pushup(int pos){
            Max[pos] = max( Max[ls(pos)], Max[rs(pos)] );
            Min[pos] = min( Min[ls(pos)], Min[rs(pos)] );
        }
        void build(int pos, int l, int r){
            if(l == r){
                Max[pos] = Min[pos] = dfn[l];
                return;
            }
            int mid = (l + r) >> 1;
            build(ls(pos), l, mid);
            build(rs(pos), mid+1, r);
            pushup(pos);
        }
        void modify(int pos, int l, int r, int x, int v){
            if(l == r && l == x){
                Max[pos] = max(Max[pos], v);
                Min[pos] = min(Min[pos], v);
                return;
            }
            int mid = (l + r) >> 1;
            if(x <= mid) modify(ls(pos), l, mid, x, v);
            else modify(rs(pos), mid+1, r, x, v);
            pushup(pos);
        }
        int QMAX(int pos, int l, int r, int x, int y){
            int ans = 0;
            if(l > y || r < x) return 0;
            if(x <= l && r <= y) return Max[pos];
            int mid = (l + r) >> 1;
            if(x <= mid) ans = max(ans, QMAX(ls(pos), l, mid, x, y));
            if(y > mid) ans = max(ans, QMAX(rs(pos), mid+1, r, x, y));
            return ans;
        }
        int QMIN(int pos, int l, int r, int x, int y){
            int ans = 0x3f3f3f3f;
            if(l > y || r < x) return 0x3f3f3f3f;
            if(x <= l && r <= y) return Min[pos];
            int mid = (l + r) >> 1;
            if(x <= mid) ans = min(ans, QMIN(ls(pos), l, mid, x, y));
            if(y > mid) ans = min(ans, QMIN(rs(pos), mid+1, r, x, y));
            return ans;
        }
    }
    using namespace Seg;
    void dfs(int u, int fa){
        dfn[u] = ++cnt; rev[cnt] = u;
        for(int i=head[u]; i; i=edge[i].nxt){
            int v = edge[i].to;
            if(v == fa) continue;
            d[v] = d[u] + 1;
            f[v][0] = u;
            dfs(v, u);
        }
    }
    int lca(int u, int v){
        if(d[u] < d[v]) swap(u, v);
        for(int i=18; i>=0; i--) if(d[f[u][i]] >= d[v]) u = f[u][i];
        if(u == v) return u;
        for(int i=18; i>=0; i--) if(f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
        return f[u][0];
    }
    int main(){
        cin >> n >> q;
        for(int i=2; i<=n; i++){
            int v; cin >> v;
            build(i, v); build(v, i);
        }
        d[1] = 1;
        dfs(1, 0);
        build(1, 1, n);
        for(int j=1; j<=18; j++)
            for(int i=1; i<=n; i++) f[i][j] = f[f[i][j-1]][j-1];
        while(q --){
            int l, r, L, Lu, R, Ru, L2, L2u, R2, R2u, LCA1, LCA2;
            int flag = 0;
            cin >> l >> r;
            L = QMIN(1, 1, n, l, r), R = QMAX(1, 1, n, l, r);
            Lu = rev[L], Ru = rev[R];
            L2 = min(QMIN(1, 1, n, l, Lu - 1), QMIN(1, 1, n, Lu + 1, r));
            R2 = max(QMAX(1, 1, n, l, Ru - 1), QMAX(1, 1, n, Ru + 1, r));
            L2u = rev[L2], R2u = rev[R2];
            LCA1 = lca(Lu, R2u); LCA2 = lca(L2u, Ru);
            if(d[LCA1] > d[LCA2]) flag = 1;
            else flag = 0;
            if(flag){
                cout << Ru << " " << d[LCA1] - 1 << endl;
            }
            else cout << Lu << " " << d[LCA2] - 1 << endl;
        }
        return 0;
    }
    

    总结

    大概猜出第一个结论就好做了。

  • 相关阅读:
    导出查询结果到excle
    导出所选行为excle
    spring security LDAP获取用户信息
    spring security防御会话伪造session攻击
    Linux安装Loadrunner generator
    Centos7 安装gitlab
    kafka 安装部署
    zookeeper 搭建
    Oracle GoldenGate对接 Oracle 11g和Kafka
    suse 11 sp4 设置yast 安装源
  • 原文地址:https://www.cnblogs.com/alecli/p/9992536.html
Copyright © 2011-2022 走看看