UOJ195,【ZJOI2016】大♂森林

这题题解看lych_cys即可,我就不赘述了。
对于lych_cys的代码,我有个细心但效果显著的优化,那就是求两点间距离时,acss(a[k].x); splay(a[k].x); ans[a[k].op]=sum[a[k].x];
x=acss(a[k].y); splay(a[k].y); ans[a[k].op]+=sum[a[k].y];
acss(x); splay(x); ans[a[k].op]-=sum[x]<<1;

可改成
inline int dis(register int u,register int v){
register int ans=a[access(u)].s,x=access(v);
ans+=a[x].s;
ans-=a[access(x)].s<<1;
return ans;
}

因为在梁大的代码中, access(x)的返回值 就是x所在重链的根,不必重新splay(x)再加上IO优化,uoj上就rk1了

#include<cstdio>
#include<cctype>
#include<algorithm>
const int N=500005;
struct LCT{
    struct node{
        int l,r,fa,s,v;
    }a[N];
    inline bool isroot(int x){
        return a[a[x].fa].l!=x && a[a[x].fa].r!=x;
    }
    inline void maintain(int x){
        a[x].s=a[a[x].l].s+a[a[x].r].s+a[x].v;
    }
    inline void rotate(register int x){
        register int y=a[x].fa,z=a[y].fa;
        if(!isroot(y)){
            if(a[z].l==y)a[z].l=x;
                else a[z].r=x;
        }
        a[x].fa=z;
        a[y].fa=x;
        if(x==a[y].l){
            a[y].l=a[x].r;
            a[a[x].r].fa=y;
            a[x].r=y;
        }else{
            a[y].r=a[x].l;
            a[a[x].l].fa=y;
            a[x].l=y;
        }
        maintain(y);
    }
    inline void splay(register int x){
        register int u,v;
        while(!isroot(x)){
            u=a[x].fa,v=a[u].fa;
            if(!isroot(u)){
                if((a[v].l==u)^(a[u].l==x))rotate(x);
                    else rotate(u);
            }
            rotate(x);
        }
        maintain(x);
    }
    inline int access(register int x){
        register int y=0;
        for(;x;y=x,x=a[x].fa){
            splay(x);
            a[x].r=y;
            maintain(x);
        }
        return y;
    }
    inline void cut(int x){
        access(x),splay(x),a[a[x].l].fa=0,a[x].l=0,maintain(x);
    }
    inline void link(int x,int y){
        splay(x);
        a[x].fa=y;
    }
    inline int dis(register int u,register int v){
        register int ans=a[access(u)].s,x=access(v);
        ans+=a[x].s;
        ans-=a[access(x)].s<<1;
        return ans;
    }
}t;
struct eve{
    int id,o,x,y;
}a[N];
int m,n,xb,cnt,b[N],l[N],r[N],i,ans[N],o,x,y,u,v,now,tot,z;
bool cmp(eve a,eve b){
    return a.id<b.id || (a.id==b.id && a.o<b.o);
}
char obuf[1500000],*oh=obuf,ibuf[7000000],*ih=ibuf;
inline void read(int&x){
    x=0;
    register char c;
    while(!isdigit(c=*ih++));
    for(;isdigit(c);c=*ih++)x=((x+(x<<2))<<1)+(c^48);
}
inline void print(register int x){
    static int buf[30];
    register int xb=0;
    if(!x)*oh++='0';
        else{
            for(;x;x/=10)buf[++xb]=x%10;
            while(xb)*oh++=buf[xb--]^48;
        }
}
int main(){
    //freopen("ex_forest2.in","r",stdin);
    //freopen("2.txt","w",stdout);
    fread(ibuf,1,7000000,stdin);
    read(n);
    read(m);
    cnt=b[1]=1,now=xb=2;
    t.a[1].v=1;
    l[1]=1,r[1]=n;
    t.link(2,1);
    for(i=1;i<=m;++i){
        ans[i]=-1;
        read(o);
        read(x);
        read(y);
        if(o==0){
            t.link(b[++cnt]=++xb,now);
            t.a[xb].v=1;
            l[cnt]=x,r[cnt]=y;
        }else read(z);
        if(o==1){
            if(l[z]>x)x=l[z];
            if(r[z]<y)y=r[z];
            if(x<=y){
                ++xb;                       
                if(x>1)t.link(xb,now);
                a[++tot]=(eve){x,-1,xb,b[z]};
                a[++tot]=(eve){y+1,-1,xb,now};
                now=xb;
            }
        }
        if(o==2)a[++tot]=(eve){x,i,b[y],b[z]};
    }
    std::sort(a+1,a+tot+1,cmp);
    for(i=1;i<=tot;++i)
        if(~a[i].o)ans[a[i].o]=t.dis(a[i].x,a[i].y);
            else t.cut(a[i].x),t.link(a[i].x,a[i].y);
    for(i=1;i<=m;++i)if(~ans[i])print(ans[i]),*oh++='\n';
    fwrite(obuf,1,oh-obuf,stdout);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值