指针版LCT

最近C语言刚学指针,想要练练手

于是写了个指针版的LCT

代码比较好理解,和非指针版的LCT差不多

但是感觉还是有点慢。。。

代码:(【模板】动态树(Link-Cut-Tree))

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gi()
{
    char c;int num=0,flg=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;   
    while(c>='0'&c<='9'){num=num*10+c-48;c=getchar();}
    return num*flg;
}
#define N 100005
#define X (*x)
#define Y (*y)
#define lc X.ch[0]
#define rc X.ch[1]
struct LCT{
    int sum,num;
    bool rev;
    LCT *ch[2];
    LCT *fa;
}a[N];
const LCT * const nu=&a[0];
void pushup(LCT* x)
{
    X.sum=(*lc).sum^(*rc).sum^X.num;
}
void pushdown(LCT* x)
{
    if(X.rev){
        swap(lc,rc);
        if(lc!=nu)(*lc).rev^=1;
        if(rc!=nu)(*rc).rev^=1;
        X.rev=0;
    }
}
bool pdc(LCT* x){return (*X.fa).ch[1]==x;}
bool pdr(LCT* x){return (*X.fa).ch[0]!=x&&(*X.fa).ch[1]!=x;}
void rot(LCT* x)
{
    LCT *y=X.fa,*z=Y.fa;
    bool flg=pdc(x);
    if(!pdr(y))(*z).ch[pdc(y)]=x;
    if((Y.ch[flg]=X.ch[flg^1])!=nu)
        (*Y.ch[flg]).fa=y;
    X.ch[flg^1]=y;
    Y.fa=x;X.fa=z;
    pushup(y);pushup(x);
}
void pdp(LCT* x)
{
    if(!pdr(x))pdp(X.fa);
    pushdown(x);
}
void splay(LCT* x)
{
    pdp(x);
    for(;!pdr(x);rot(x))
        if(!pdr(X.fa))
            rot(pdc(x)==pdc(X.fa)?X.fa:x);
}
LCT* Access(LCT* x)
{
    LCT* p=&a[0];
    for(;x!=nu;p=x,x=X.fa){
        splay(x);
        X.ch[1]=p;
        pushup(x);
    }
    return p;
}
LCT* LCA(LCT* x,LCT* y)
{
    Access(x);
    return Access(y);
}
void beroot(LCT* x)
{
    Access(x);
    splay(x);
    X.rev^=1;
}
LCT* findroot(LCT* x)
{
    Access(x);
    splay(x);
    while(X.ch[0]!=nu)
        x=X.ch[0];
    return x;
}
void link(LCT* x,LCT* y)
{
    beroot(x);
    X.fa=y;
}
void cut(LCT* x,LCT* y)
{
    beroot(x);
	Access(y);
	splay(y);
    if(x==Y.ch[0]){
        Y.ch[0]=X.fa=&a[0];
	    pushup(y);
    }
}
int getsum(LCT* x,LCT* y)
{
    beroot(x);
	Access(y);
	splay(y);
	return Y.sum;
}
int main()
{
    int n,m,i,op,nx,ny;
    n=gi();m=gi();
    for(i=0;i<=n;i++){
        if(i>0)a[i].num=a[i].sum=gi();
        a[i].ch[0]=a[i].ch[1]=a[i].fa=&a[0];
    }
    for(i=1;i<=m;i++){
        op=gi();nx=gi();ny=gi();
        if(op<=2){
            LCT *x=&a[nx],*y=&a[ny];
            if(op==0)
                printf("%d\n",getsum(x,y));
            else if(op==1){
                LCT *fx=findroot(x),*fy=findroot(y);
                if(fx!=fy)link(x,y);
            }
            else if(op==2)cut(x,y);
        }
        else{
            LCT *x=&a[nx];
            beroot(x);
            X.num=ny;
            pushup(x);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值