zoukankan      html  css  js  c++  java
  • [BZOJ 3306] 树

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=3306

    [算法]

             若没有换根操作 , 那么“查询子树最小值”就可以用DFS序 + 线段树解决

             进一步地 , 可以发现换根后 , 造成影响的点在原根到新根的路径上 , 根据这个性质 , 问题得到解决

             时间复杂度 : O(NlogN)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 100010
    #define MAXLOG 20
    const int inf = 2e9;
    typedef long long ll;
    typedef long double ld;
    
    struct edge
    {
            int to , nxt;
    } e[MAXN << 2];
    
    int n , q , rt , timer , tot;
    int dfn[MAXN] , l[MAXN] , r[MAXN] , value[MAXN] , loc[MAXN] , head[MAXN] , depth[MAXN];
    int up[MAXN][MAXLOG];
    
    struct Segment_Tree
    {
            struct Node
            {
                    int l , r;
                    int Min;    
            }    Tree[MAXN << 2];
            inline void update(int index)
            {
                    Tree[index].Min = min(Tree[index << 1].Min , Tree[index << 1 | 1].Min);
            }
            inline void build(int index , int l , int r)
            {
                    Tree[index].l = l;
                    Tree[index].r = r;
                    if (l == r)
                    {
                            Tree[index].Min = value[loc[l]];
                            return;
                    }
                    int mid = (l + r) >> 1;
                    build(index << 1 , l , mid);
                    build(index << 1 | 1 , mid + 1 , r);
                    update(index);
            }
            inline void modify(int index , int pos , int v)
            {
                    if (Tree[index].l == Tree[index].r)
                    {
                            Tree[index].Min = v;
                            return;
                    }
                    int mid = (Tree[index].l + Tree[index].r) >> 1;
                    if (mid >= pos) modify(index << 1 , pos , v);
                    else modify(index << 1 | 1 , pos , v);
                    update(index);
            }
            inline int query(int index , int l , int r)
            {
                    if (l > r) return inf;
                    if (Tree[index].l == l && Tree[index].r == r)
                            return Tree[index].Min;
                    int mid = (Tree[index].l + Tree[index].r) >> 1;
                    if (mid >= r) return query(index << 1 , l , r);
                    else if (mid + 1 <= l) return query(index << 1 | 1 , l , r);
                    else return min(query(index << 1 , l , mid) , query(index << 1 | 1 , mid + 1 , r));
            }
            inline int query()
            {
                    return Tree[1].Min;
            }
    } SGT;
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u , int v)
    {
            ++tot;
            e[tot] = (edge){v , head[u]};
            head[u] = tot;
    }
    inline void dfs(int u , int father)
    {
            depth[u] = depth[father] + 1;
            dfn[u] = l[u] = ++timer;
            loc[timer] = u;
            up[u][0] = father;
            for (int i = 1; i < MAXLOG; i++) up[u][i] = up[up[u][i - 1]][i - 1];
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (v == father) continue;
                    dfs(v , u);        
            }        
            r[u] = timer;
    }
    
    int main()
    {
            
            scanf("%d%d" , &n , &q);
            for (int i = 1; i <= n; i++)
            {
                    int f;
                    scanf("%d%d" , &f , &value[i]);
                    if (f > 0) addedge(f , i);        
                    else rt = i;        
            } 
            dfs(rt , 0);
            SGT.build(1 , 1 , n);
            while (q--)
            {
                    char type[5];
                    scanf("%s" , &type);
                    if (type[0] == 'V')
                    {
                            int x , y;
                            scanf("%d%d" , &x , &y);
                            SGT.modify(1 , dfn[x] , y);
                    } else if (type[0] == 'E')
                    {
                            int x;
                            scanf("%d" , &x);
                            rt = x;
                    } else
                    {
                            int x;
                            scanf("%d" , &x);
                            if (x == rt) printf("%d
    " , SGT.query());
                            else if (l[x] <= l[rt] && r[x] >= r[rt])
                            {
                                    int y = rt;
                                    for (int i = MAXLOG - 1; i >= 0; i--)
                                    {
                                            if (depth[up[y][i]] > depth[x])
                                                    y = up[y][i];
                                    }
                                    printf("%d
    " , min(SGT.query(1 , 1 , l[y] - 1) , SGT.query(1 , r[y] + 1 , n)));
                            } else printf("%d
    " , SGT.query(1 , l[x] , r[x]));
                    }
            }
            
            return 0;
        
    }
  • 相关阅读:
    设计模式学习总结系列应用实例
    【研究课题】高校特殊学生的发现及培养机制研究
    Linux下Oracle11G RAC报错:在安装oracle软件时报file not found一例
    python pro practice
    openstack python sdk list tenants get token get servers
    openstack api
    python
    git for windows
    openstack api users list get token get servers
    linux 流量监控
  • 原文地址:https://www.cnblogs.com/evenbao/p/10054393.html
Copyright © 2011-2022 走看看