1 条题解

  • 0
    @ 2026-1-12 10:45:32
    #include<cstdio>
    #include<cstdlib>
    #define R register int
    #define I inline void
    const int N=100009,INF=2147483647;
    int f[N],c[N][2],si[N],s[N],h[N];
    bool r[N];
    #define lc c[x][0]
    #define rc c[x][1]
    inline bool nroot(R x){return c[f[x]][0]==x||c[f[x]][1]==x;}
    I pushup(R x){
        s[x]=s[lc]+s[rc]+si[x]+1;
    }
    I pushdown(R x){
        if(r[x]){
            R t=lc;lc=rc;rc=t;
            r[lc]^=1;r[rc]^=1;r[x]=0;
        }
    }
    I pushall(R x){
        if(nroot(x))pushall(f[x]);
        pushdown(x);
    }
    I rotate(R x){
        R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
        if(nroot(y))c[z][c[z][1]==y]=x;
        f[f[f[c[c[x][!k]=y][k]=w]=y]=x]=z;pushup(y);//为三行rotate打call
    }
    I splay(R x){
        pushall(x);
        R y;
        while(nroot(x)){
        	if(nroot(y=f[x]))rotate((c[f[y]][0]==y)^(c[y][0]==x)?x:y);
        	rotate(x);
        }
        pushup(x);
    }
    I access(R x){
        for(R y=0;x;x=f[y=x]){
            splay(x);
            si[x]+=s[rc];
            si[x]-=s[rc=y];
            pushup(x);
        }
    }
    I makeroot(R x){
        access(x);splay(x);
        r[x]^=1;
    }
    I split(R x,R y){
        makeroot(x);
        access(y);splay(y);
    }
    I link(R x,R y){
        split(x,y);
        si[f[x]=y]+=s[x];
        pushup(y);
    }
    int geth(R x){
        if(h[x]==x)return x;
        return h[x]=geth(h[x]);
    }
    inline int update(R x){
        R l,r,ji=s[x]&1,sum=s[x]>>1,lsum=0,rsum=0,newp=INF,nowl,nowr;
        while(x){
            pushdown(x);//注意pushdown
            nowl=s[l=lc]+lsum;nowr=s[r=rc]+rsum;
            if(nowl<=sum&&nowr<=sum){
                if(ji){newp=x;break;}//剪枝,确定已经直接找到
                else if(newp>x)newp=x;//选编号最小的
            }
            if(nowl<nowr)lsum+=s[l]+si[x]+1,x=r;
            else         rsum+=s[r]+si[x]+1,x=l;//缩小搜索区间
        }
        splay(newp);//保证复杂度
        return newp;
    }
    #define G ch=getchar()
    #define gc G;while(ch<'-')G
    #define in(z) gc;z=ch&15;G;while(ch>'-')z*=10,z+=ch&15,G;
    int main(){
        register char ch;
        R n,m,x,y,z,Xor=0;
        in(n);in(m);
        for(R i=1;i<=n;++i)s[i]=1,h[i]=i,Xor^=i;
        while(m--){
        	gc;
        	switch(ch){
        		case 'A':in(x);in(y);link(x,y);
        			split(x=geth(x),y=geth(y));//提出原重心路径
        			z=update(y);
        			Xor=Xor^x^y^z;
        			h[x]=h[y]=h[z]=z;//并查集维护好
        			break;
        		case 'Q':in(x);printf("%d\n",geth(x));break;
        		case 'X':gc;gc;printf("%d\n",Xor);
        	}
        }
        return 0;
    }
    
    • 1

    信息

    ID
    5175
    时间
    1000ms
    内存
    128MiB
    难度
    10
    标签
    递交数
    2
    已通过
    2
    上传者