bzoj4764: 弹飞大爷 link-cut-tree

Posted 友人A

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4764: 弹飞大爷 link-cut-tree相关的知识,希望对你有一定的参考价值。

题目传送门

这道题啊 调了一个晚上 因为写的是一个有根树和n个基环的写法 所以写得很奇怪..... 最后发现单独处理树的时候不能随意改变S(就是原来的根)不然size会出错.... 

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int M=250007;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int c[M][2],fa[M],size[M],rev[M],lx[M],rx[M],sum[M];
int n,m;
bool isrt(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
void up(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;}
void down(int x){
    //printf("~~~%d\n",x);
    int l=c[x][0],r=c[x][1];
    if(rev[x]){
        if(l) swap(c[l][0],c[l][1]),rev[l]^=1;
        if(r) swap(c[r][0],c[r][1]),rev[r]^=1;
        rev[x]=0;
    }
    int u=lx[x],v=rx[x];
    if(l) lx[l]=u,rx[l]=v;
    if(r) lx[r]=u,rx[r]=v;
}
void rotate(int x){
    int y=fa[x],z=fa[y],l=0,r=1;
    if(c[y][1]==x) l=1,r=0;
    if(!isrt(y)) c[z][c[z][1]==y]=x;
    fa[y]=x; fa[x]=z; fa[c[x][r]]=y;
    c[y][l]=c[x][r]; c[x][r]=y;
    up(y); up(x);
}
int st[M],top=0,S;
void test()
{
    cout<<"No "<<endl;
    for (int j=1;j<=n+1;j++)
        cout<<j<<" son"<<c[j][0]<< <<c[j][1]<<" fa"<<fa[j]<<" rev"<<rev[j]<<" size"<<size[j]<<" edge"<<lx[j]
        <<rx[j]<<endl;cout<<endl;
}
void splay(int x){
    st[++top]=x; for(int i=x;!isrt(i);i=fa[i]) st[++top]=fa[i];
    while(top) down(st[top--]);
    while(!isrt(x)){
        int y=fa[x],z=fa[y];
        if(!isrt(y)){
            if(c[z][0]==y^c[y][0]==x) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
}
void acs(int x0){
    for(int x=x0,y=0;x;splay(x),c[x][1]=y,up(x),y=x,x=fa[x]);
    splay(x0);
}
void mrt(int x){acs(x); swap(c[x][0],c[x][1]); rev[x]^=1;}
int find(int x){
    acs(x); while(c[x][0]) x=c[x][0];
    return x;
}
void push_link(int x,int y){mrt(x); fa[x]=y; acs(x);}
void link(int x,int y){
    if(find(x)==find(y)) lx[y]=x,rx[y]=y;
    else push_link(x,y);//printf("%d %d\n",x,y);
}
//void dfs(int x){
//    if(!x) return ;
//    printf("~~~%d\n",x);
//    dfs(c[x][0]); 
//    dfs(c[x][1]);
//}
int push_ans(int x){
    acs(x);  if(lx[x]&&rx[x]) return -1;
    //dfs(x);
    return size[x]-1;
}
void cut(int x,int y){mrt(x); acs(y); /*cout<<"cuttest2"<<endl;test();*/c[y][0]=fa[x]=0; up(y); lx[x]=rx[x]=lx[y]=rx[y]=0;}
void push_cut(int x,int y){
    acs(x); int l=lx[x],r=rx[x];
    if(l==x&&r==y) lx[x]=rx[x]=0;
    else{
        cut(x,y); //printf("%d %d\n",x,y);
        if(l&&r) link(l,r);
    }
}
int main()
{
    int k,x,w;
    n=read(); m=read(); S=n+1;
    for(int i=1;i<=S;i++) size[i]=1;
    for(int i=1;i<=n;i++){
        k=read(); sum[i]=k;
        if(i+k<=0||i+k>n) push_link(i,S);
        else link(i,i+k);
    }
    for(int i=1;i<=m;i++){
        k=read();
        if(k==1) x=read(),mrt(S),printf("%d\n",push_ans(x));
        else{
            x=read(); w=read();
            if(x+sum[x]<=0||x+sum[x]>n) cut(x,S);
            else push_cut(x,x+sum[x]);//printf("~%d %d\n",x,x+sum[x]);
//            cout<<"cutfinish"<<endl;test();
            if(x+w<=0||x+w>n) push_link(x,S); //printf("~~~\n");
            else link(x,x+w);//printf("%d %d\n",x,x+w);
            sum[x]=w;
        }
        //test();
    }
    return 0;
}
View Code

 

以上是关于bzoj4764: 弹飞大爷 link-cut-tree的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4764弹飞大爷 LCT

LCT维护基环内向树森林BZOJ4764 弹飞大爷

bzoj4764 弹飞大爷 LCT

bzoj4764 弹飞大爷

BZOJ4764 弹飞大爷

bzoj4764: 弹飞大爷 link-cut-tree