BZOJ 4736: 温暖会指引我们前行(LCT)

题目

分析

动态维护一颗最大生成树,注意查询的值不是用来做最大生成树的那个权值。

具体就是把边变成点。一些查找要素都可以放在splay中查找。

还有就是要注意如果有一条边不选的话,那么我们可能不会为它建立结点,所以要特判一下修改的时候它是不是出现了,出现了就不管。

代码

#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define lc ch[now][0]
#define rc ch[now][1]
const int maxn=4e5+105,inf=2e9;
int n,m;
char s[10];
int mp[maxn];
struct Link_Cut_Tree
{
    int np,ch[maxn][2],fa[maxn],w[maxn],mi[maxn],sum[maxn],dist[maxn],L[maxn],R[maxn],num[maxn];
    bool rev[maxn];
    void Initial()
    {
        np=n;
    }
    void pushup(int now)
    {
        mi[now]=w[now];
        sum[now]=dist[now];
        num[now]=now;
        if(lc)
        {
            sum[now]+=sum[lc];
            if(mi[lc]if(rc)
        {
            sum[now]+=sum[rc];
            if(mi[rc]void pushdown(int now)
    {
        if(rev[now])
        {
            swap(lc,rc);
            rev[lc]^=1;
            rev[rc]^=1;
            rev[now]=0;
        }
    }
    bool is_rt(int now)
    {
        return ch[fa[now]][0]!=now && ch[fa[now]][1]!=now;
    }
    void Link(int i,int d,int j)
    {
        ch[i][d]=j;
        fa[j]=i;
    }
    void rot(int x)
    {
        int y=fa[x],z=fa[y];
        pushdown(y);pushdown(x);
        int d=(ch[y][1]==x);
        if(!is_rt(y))Link(z,ch[z][1]==y,x);fa[x]=z;
        Link(y,d,ch[x][d^1]);
        Link(x,d^1,y);
        pushup(y);pushup(x);
    }
    void Splay(int x)
    {
        pushdown(x);//果然要加这一句 
        while(!is_rt(x))
        {
            int y=fa[x],z=fa[y];
            if(!is_rt(y)) rot((ch[y][0]==x)==(ch[z][0]==y)?y:x);
            rot(x);
        }
    }

    int acc(int x)
    {
        int y=0;
        while(x)
        {
            Splay(x);
            ch[x][1]=y;
            pushup(x);

            y=x;
            x=fa[x];
        }
        return y;
    }
    void mroot(int x)
    {
        acc(x);Splay(x);rev[x]^=1;
    }
    int Find(int x)
    {
        acc(x);
        Splay(x);
        while(ch[x][0])
        {
            pushdown(x);
            x=ch[x][0];
        }
        return x;
    }

    void link(int x,int y)
    {
        mroot(x);fa[x]=y;
    }
    void cut(int x,int y)
    {
        mroot(x);acc(y);Splay(y);
        fa[ch[y][0]]=0;ch[y][0]=0;pushup(y);
    }

    int query(int x,int y)
    {
        if(Find(x)!=Find(y))return -1;
        mroot(x);acc(y);Splay(y);
        return sum[y];
    }
    int mylink(int x,int y,int t,int l)
    {
        ++np;
        w[np]=t;
        dist[np]=l;
        pushup(np);
        L[np]=x;R[np]=y;
        link(x,np);
        link(y,np);
        return np;
    }
    void myCut(int x)
    {
        cut(x,L[x]);
        cut(x,R[x]);
    }
    void add(int x,int y,int t,int l,int id)//尝试在x,y,w之间连边 
    {
        if(Find(x)!=Find(y))
        {
            mp[id]=mylink(x,y,t,l);
            return;
        }
        mroot(x);acc(y);Splay(y);
        if(mi[y]>=t)return;
        myCut(num[y]);
        mp[id]=mylink(x,y,t,l);
    }
    void change(int id,int l)
    {
        int x=mp[id];
        if(!x)return;
        Splay(x);
        dist[x]=l;
        pushup(x);
    }
}lct;
//把所有的id都加上n+1 
void Init()
{
    scanf("%d%d",&n,&m);
    lct.Initial();
    for(int i=1;i<=n;i++)lct.w[i]=inf,lct.pushup(i);
}
void query()
{
    int u,v,id,t,l;
    while(m--)
    {
        scanf("%s",s);
        if(s[0]=='f')
        {
            scanf("%d%d%d%d%d",&id,&u,&v,&t,&l);u++,v++;
            lct.add(u,v,t,l,id);
        }
        else if(s[0]=='m')
        {
            scanf("%d%d",&u,&v);u++,v++;
            printf("%d\n",lct.query(u,v));
        }
        else
        {
            scanf("%d%d",&id,&l);
            lct.change(id,l);
        }
    }
}
int main()
{
    //freopen("road.in","r",stdin);
    //freopen("road.out","w",stdout);
    Init();
    query();
    return 0;
}

你可能感兴趣的:(LCT,BZOJ)