[BZOJ 3083] 遥远的国度

[题目链接]

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

[算法]

         树链剖分

         时间复杂度 : O(NlogN ^ 2)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
#define MAXLOG 20
const int inf = 2e9;

struct edge
{
        int to , nxt;
} e[MAXN << 1];

int n , q , tot , timer , rt;
int a[MAXN] , head[MAXN] , dfn[MAXN] , l[MAXN] , r[MAXN] , fa[MAXN] , loc[MAXN] , son[MAXN] , size[MAXN] , top[MAXN] , depth[MAXN];
int up[MAXN][MAXLOG];

struct Segment_Tree
{
        struct Node
        {
                int l , r;
                int value , tag;
        } Tree[MAXN << 2];
        inline void update(int index)
        {
                Tree[index].value = min(Tree[index << 1].value , Tree[index << 1 | 1].value);
        }
        inline void pushdown(int index)
        {
                if (Tree[index].tag != -1)
                {
                        Tree[index << 1].value = Tree[index << 1 | 1].value = Tree[index].tag;
                        Tree[index << 1].tag = Tree[index << 1 | 1].tag = Tree[index].tag;
                        Tree[index].tag = -1;
                }
        }
        inline void build(int index , int l , int r)
        {
                Tree[index].l = l;
                Tree[index].r = r;
                Tree[index].tag = -1;
                if (l == r)
                {
                        Tree[index].value = a[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 l , int r , int val)
        {
                if (Tree[index].l == l && Tree[index].r == r)
                {
                        Tree[index].value = val;
                        Tree[index].tag = val;
                        return;
                }
                pushdown(index);
                int mid = (Tree[index].l + Tree[index].r) >> 1;
                if (mid >= r) modify(index << 1 , l , r , val);
                else if (mid + 1 <= l) modify(index << 1 | 1 , l , r , val);
                else
                {
                        modify(index << 1 , l , mid , val);
                        modify(index << 1 | 1 , mid + 1 , r , val);
                }
                update(index);
        }
        inline int query()
        {
                return Tree[1].value;
        }
        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].value;
                pushdown(index);
                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));
        }
} 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 dfs1(int u , int father)
{
        son[u] = 0;
        size[u] = 1;
        depth[u] = depth[father] + 1;
        up[u][0] = father;
        fa[u] = 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;
                dfs1(v , u);
                size[u] += size[v];
                if (son[u] == 0 || size[v] > size[son[u]]) son[u] = v;
        }                
}
inline void dfs2(int u , int t)
{
        dfn[u] = l[u] = ++timer;
        loc[timer] = u;
        top[u] = t;
        if (son[u]) dfs2(son[u] , t);
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to;
                if (v != fa[u] && v != son[u]) dfs2(v , v);        
        }        
        r[u] = timer;
}
inline void modify(int u , int v , int w)
{
        int tu = top[u] , tv = top[v];
        while (tu != tv)
        {
                if (depth[tu] > depth[tv])    
                {
                        swap(u , v);
                        swap(tu , tv);        
                }    
                SGT.modify(1 , dfn[tv] , dfn[v] , w);
                v = fa[tv]; tv = top[v];
        }         
        if (dfn[u] > dfn[v]) swap(u , v);
        SGT.modify(1 , dfn[u] , dfn[v] , w);
}

int main()
{
        
        read(n); read(q);
        for (int i = 1; i < n; i++)
        {
                int u , v;
                read(u); read(v);
                addedge(u , v);
                addedge(v , u);
        }
        for (int i = 1; i <= n; i++) read(a[i]);
        read(rt);
        dfs1(rt , 0);
        dfs2(rt , rt);
        SGT.build(1 , 1 , n);
        while (q--)
        {
                int type;
                read(type);
                if (type == 1)
                {
                        int x;
                        read(x);
                        rt = x;        
                }    else if (type == 2)
                {
                        int u , v , w;
                        read(u); read(v); read(w);
                        modify(u , v , w);
                } else
                {
                        int x;
                        read(x);
                        if (x == rt) printf("%d\n" , 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\n" , min(SGT.query(1 , 1 , l[y] - 1) , SGT.query(1 , r[y] + 1 , n)));
                        } else printf("%d\n" , SGT.query(1 , l[x] , r[x]));
                }
        }
        
        return 0;
    
}

 

posted @ 2018-12-02 22:22  evenbao  阅读(165)  评论(0编辑  收藏  举报