zoukankan      html  css  js  c++  java
  • 3306: 树(线段树)

    3306: 树

    1.思路

      首先dfs整颗树将树转换线性结构,前两个操作比较简单,然后主要是对于操作三,有三种情况:

        1.x=rt,那么我们直接求出整颗树中的最小值就是答案;

        2.x在原树中为rt的祖先节点,那么我们首先求出从x到rt路径上的x的第一个节点y,那么答案就是除了以y为根的子树的其他所有节点的最小值;

        3.对于除了以上两种情况,直接求出以x为根的子树的最小值即为答案.

        

    2.代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 2e5+5;
    #define ls rt<<1
    #define rs rt<<1|1
    
    struct Edge{
        int to, next;  
    };
    
    Edge e[N];
    int head[N];
    int dep[N];
    int tot;
    
    void addEdge(int u, int v) {
        e[++tot] = Edge{v, head[u]};
        head[u] = tot;
    }
    
    int a[N], b[N];
    int l[N], r[N];
    int dfs_clock;
    int f[N][20];
    void dfs(int u) {
        l[u] = ++ dfs_clock;
        a[dfs_clock] = b[u];
        for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            dep[to] = dep[u] + 1;
            f[to][0] = u;
            dfs(to);
        }
        r[u] = dfs_clock;
    }
    
    int v[N<<2];
    inline void pushUp(int rt) {
        v[rt] = v[ls] < v[rs]? v[ls] : v[rs];
    } 
    
    void build(int rt, int l, int r) {
        if(l == r) {
            v[rt] = a[l];
            return ;
        }
        int mid = (l + r) >> 1;
        build(ls, l, mid);
        build(rs, mid+1, r);
        pushUp(rt);
    }
    
    void update(int rt, int l, int r, int a, int b) {
        if(l == r) {
            v[rt] = b;
            return ;
        }
        int mid = (l + r) >> 1;
        if(a <= mid) {
            update(ls, l, mid, a, b);
        }
        else {
            update(rs, mid+1, r, a, b);
        }
        pushUp(rt);
    }
    
    int query(int rt, int l, int r, int a, int b) {
        if(a > b) return INT_MAX;
        if(a <= l && r <= b) {
            return v[rt]; 
        }
        int mid = (l + r) >> 1;
        int res = INT_MAX;
        if(a <= mid) {
            res = min(res, query(ls, l, mid, a, b));
        }
        if(b > mid) {
            res = min(res, query(rs, mid+1, r, a, b));
        }
        return res;
    }
    
    void initLca(int n) {
        for(int j = 1; j < 20; ++ j) {
            for(int i = 1; i <= n; ++ i) {
                f[i][j] = f[f[i][j-1]][j-1];
            }
        }
    }
    
    int go(int x, int d) {
        for(int i = 0; i < 20; ++ i) {
            if(d&(1<<i)) {
                x = f[x][i];
            }
        }
        return x;
    }
    
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        int rt;
        for(int i = 1; i <= n; ++ i) {
            int x;
            scanf("%d%d", &x, &b[i]);
            if(x == 0) rt = i;
            else addEdge(x, i);
        } 
        dfs(rt);
        build(1, 1, n);
        initLca(n);
        while(m --) {
            char op[5];
            scanf("%s", op);
            if(op[0] == 'Q') {
                int x;
                scanf("%d", &x);
                if(x == rt) {
                    printf("%d
    ", v[1]);
                }
                /*  error
                else if(dep[x] > dep[rt]) {
                    int res = query(1, 1, n, l[x], r[x]);
                    printf("%d
    ", res);
                } 
                */
                else if(l[x] < l[rt] && r[x] >= r[rt]) {
                    int di = dep[rt] - dep[x] - 1; 
                    int y = go(rt, di);
                    int res = query(1, 1, n, 1, l[y]-1);
                    res = min(res, query(1, 1, n, r[y]+1, n));
                    printf("%d
    ", res);
                }
                else {
                    int res = query(1, 1, n, l[x], r[x]);
                    printf("%d
    ", res);
                }
            }
            else if(op[0] == 'V'){
                int x, y;
                scanf("%d%d", &x, &y);
                update(1, 1, n, l[x], y);
            }
            else {
                scanf("%d", &rt);
            }
        }
    
        return 0;
    }
    

      

     
  • 相关阅读:
    springboot实现redis的分布式锁
    剑指offer--二维数组中查找
    剑指offer--二维数组中查找
    对JDK动态代理的模拟实现
    Spring(4)AOP
    设计模式之单例模式(Java)
    【Java并发系列】--Java内存模型
    maven 解决jar包冲突及简单使用
    基于注解的SpringAOP源码解析(三)
    Java代码中可以优化性能的小细节
  • 原文地址:https://www.cnblogs.com/topk/p/7704492.html
Copyright © 2011-2022 走看看