uoj#274. 【清华集训2016】温暖会指引我们前行 //LCT

uoj#274.【清华集训2016】温暖会指引我们前行


题意

N≤1e5个点,M≤3e5个操作。
每条边有一个权值T(保证互异)和一个长度L,资磁加边、改变一条边的L、询问u到v在关于T的最大生成树上的路径长度。


题解

这题主要难度大概都在读题上…。
lct模板题我怎么整天写模板题啊,维护一下最大生成树即可。
txl学长说那个高级的边权lct写法并不比拆点优越到哪里去…所以写了一发边拆点的lct 感觉并不很麻烦嘛


代码

UPD:原来那个直接getroot的被negii hack掉了…
不splay的话复杂度的确会炸
然后我lct好像以前一直是那么写的…。太可怕了(

#include<bits/stdc++.h>
#define N 200005
#define M 300005
#define pf(x) (c[f[x]][0]==x||c[f[x]][1]==x)
using namespace std;
int n,m,tem[N],len[N],mn[N],sl[N],cct;
int id[M],di[N],c[N][2],f[N];
bool rev[N];
inline void reverse(int x)
{rev[x]^=1,swap(c[x][0],c[x][1]);}
inline void pushdown(int x)
{if(rev[x])rev[x]=0,reverse(c[x][0]),reverse(c[x][1]);}
void pd(int x)
{if(pf(x))pd(f[x]);pushdown(x);}
inline void update(int x)
{
    mn[x]=x,sl[x]=len[x];
    if(c[x][0])sl[x]+=sl[c[x][0]],
    mn[x]=tem[mn[x]]>tem[mn[c[x][0]]]?mn[c[x][0]]:mn[x];
    if(c[x][1])
    sl[x]+=sl[c[x][1]],
    mn[x]=tem[mn[x]]>tem[mn[c[x][1]]]?mn[c[x][1]]:mn[x];
}
inline void rotate(int x,bool t)
{
    int y=f[x];
    if(pf(y))c[f[y]][c[f[y]][1]==y]=x;
    f[x]=f[y],f[y]=x,f[c[x][t]]=y;
    c[y][t^1]=c[x][t],c[x][t]=y;
    update(y),update(x);
}
inline void splay(int x)
{
    pd(x);
    int y;bool t1,t2;
    while(pf(x))
    {
        t1=c[y=f[x]][0]==x,t2=c[f[y]][0]==y;
        if(!pf(y)){rotate(x,t1);return;}
        if(t1^t2)rotate(x,t1),rotate(x,t2);
        else rotate(y,t2),rotate(x,t1);
    }
}
inline void access(int x)
{
    int y=0;
    while(x)
    splay(x),c[x][1]=y,update(x),
    y=x,x=f[x];
}
inline void exroot(int x)
{access(x);splay(x);reverse(x);}
inline int getroot(int x)
{
    pushdown(x);
    while(c[x][0])
    x=c[x][0],pushdown(x);
    splay(x);
    return x;
}
char op[10];
int d,u,v,t,l,w;
int main()
{
    scanf("%d%d",&n,&m),cct=n;
    for(int i=1;i<=n;i++)
    tem[i]=2e9,update(i);
    while(m--)
    {
        scanf("%s",op);
        if(op[0]=='f')
        {
            scanf("%d%d%d%d%d",&d,&u,&v,&t,&l);
            u++,v++;
            exroot(u),access(v),splay(v),w=mn[v];
            if(getroot(v)==u)
            {
                if(tem[w]<t)
                {
                    splay(w),f[c[w][0]]=f[c[w][1]]=0;
                    c[w][0]=c[w][1]=0;
                    id[di[w]]=-1;
                }
                else {id[d]=-1;continue;}
            }
            else w=++cct;
            tem[w]=t,len[w]=l,id[d]=w,di[w]=d;
            update(w);
            exroot(u),f[u]=w;exroot(w),f[w]=v;
        }
        if(op[0]=='m')
        {
            scanf("%d%d",&u,&v);u++,v++;
            exroot(u);
            access(v),splay(v),w=sl[v];
            printf("%d\n",(getroot(v)^u)?-1:w);
        }
        if(op[0]=='c')
        {
            scanf("%d%d",&d,&l);
            if(id[d]^-1)
            splay(id[d]),len[id[d]]=l,update(id[d]);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Starria/article/details/78889010
LCT