BZOJ 3306 树 Link-Cut-Tree+set

题目大意:给定一棵有根树,每个点有个权值,要求维护换根、单点修改、查询子树最小值

闲得我写了发LCT……
(这段时间咋净写LCT了。。。

每个节点开一个multiset记录一下所有虚边连接的子树的最小值
然后切换虚边的时候把原来的实边连接的子树扔进multiset,把新的实边连接的子树从multiset里删除就行了
时间复杂度 O(nlog2n)

#include <set>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
int n,m,a[M];
namespace Link_Cut_Tree{
    struct abcd{
        abcd *ls,*rs,*fa;
        multiset<int> s;
        int min_val;
        bool rev_mark;
        abcd(int _);
        void Push_Up();
        void Push_Down();
        void Reverse();
    }*null=new abcd(0x7fffffff),*tree[M];
    abcd :: abcd(int _)
    {
        ls=rs=fa=null;
        s.insert(_);
        min_val=_;
        rev_mark=false;
    }
    void abcd :: Push_Up()
    {
        min_val=min(min(ls->min_val,rs->min_val),*(s.begin()));
    }
    void abcd :: Push_Down()
    {
        if(fa->ls==this||fa->rs==this)
            fa->Push_Down();
        if(rev_mark)
        {
            ls->Reverse();
            rs->Reverse();
            rev_mark=false;
        }
    }
    void abcd :: Reverse()
    {
        swap(ls,rs);
        rev_mark^=1;
    }
    void Zig(abcd *x)
    {
        abcd *y=x->fa;
        y->ls=x->rs;
        x->rs->fa=y;
        x->rs=y;
        x->fa=y->fa;
        if(y==y->fa->ls)
            y->fa->ls=x;
        else if(y==y->fa->rs)
            y->fa->rs=x;
        y->fa=x;
        y->Push_Up();
    }
    void Zag(abcd *x)
    {
        abcd *y=x->fa;
        y->rs=x->ls;
        x->ls->fa=y;
        x->ls=y;
        x->fa=y->fa;
        if(y==y->fa->ls)
            y->fa->ls=x;
        else if(y==y->fa->rs)
            y->fa->rs=x;
        y->fa=x;
        y->Push_Up();
    }
    void Splay(abcd *x)
    {
        x->Push_Down();
        while(x->fa->ls==x||x->fa->rs==x)
        {
            abcd *y=x->fa,*z=y->fa;
            if(x==y->ls)
            {
                if(y==z->ls)
                    Zig(y);
                Zig(x);
            }
            else
            {
                if(y==z->rs)
                    Zag(y);
                Zag(x);
            }
        }
        x->Push_Up();
    }
    void Access(abcd *x)
    {
        abcd *y=null;
        while(x!=null)
        {
            Splay(x);
            if(x->rs!=null)
                x->s.insert(x->rs->min_val);
            x->rs=y;
            if(y!=null)
                x->s.erase(x->s.find(y->min_val));
            x->Push_Up();
            y=x;x=x->fa;
        }
    }
    void Move_To_Root(abcd *x)
    {
        Access(x);
        Splay(x);
        x->Reverse();
    }
}
struct edge{
    int to,next;
}table[M<<1];
int head[M],tot;
void Add(int x,int y)
{
    table[++tot].to=y;
    table[tot].next=head[x];
    head[x]=tot;
}
void DFS(int x)
{
    using namespace Link_Cut_Tree;
    int i;
    tree[x]=new abcd(a[x]);
    for(i=head[x];i;i=table[i].next)
    {
        DFS(table[i].to);
        tree[table[i].to]->fa=tree[x];
        tree[x]->s.insert(tree[table[i].to]->min_val);
    }
    tree[x]->Push_Up();
}
int main()
{
    using namespace Link_Cut_Tree;
    int i,x,y;
    char p[10];
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&a[i]);
        if(x) Add(x,i);
    }
    DFS(1);
    for(i=1;i<=m;i++)
    {
        scanf("%s",p);
        if(p[0]=='V')
        {
            scanf("%d%d",&x,&y);
            Access(tree[x]);
            Splay(tree[x]);
            tree[x]->s.erase(tree[x]->s.find(a[x]));
            a[x]=y;
            tree[x]->s.insert(a[x]);
            tree[x]->Push_Up();
        }
        else if(p[0]=='E')
        {
            scanf("%d",&x);
            Move_To_Root(tree[x]);
        }
        else
        {
            scanf("%d",&x);
            Access(tree[x]);
            Splay(tree[x]);
            printf("%d\n",*(tree[x]->s.begin()));
        }
    }
    return 0;
}

你可能感兴趣的:(set,bzoj,LCT,BZOJ3306)