P4299 首都

Posted y2823774827y

tags:

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

题目

P4299 首都

做法

这题是动态维护树的重心,连边后找到两棵树的重心拉一条链(性质:新重心在链上),然后暴力爬

要注意的一点是找重心的过程中要先把旋转标记放下来,因为(Splay(x)),这个操作只把(x)到根节点的跟上旋有关标记放下来

而找重心过程中跟整个链有关

My complete code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef int LL;
const LL maxn=200000,inf=0x3f3f3f3f;
inline LL Read(){
    LL x(0),f(1);char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*f;
}
LL n,m,Xor;
LL son[maxn][2],fa[maxn],sta[maxn],f[maxn],isum[maxn],sum[maxn],r[maxn];
inline void Update(LL x){
    sum[x]=sum[son[x][0]]+sum[son[x][1]]+isum[x]+1;
}
inline bool Notroot(LL x){
    return son[fa[x]][0]==x||son[fa[x]][1]==x;
}
inline void Pushr(LL x){
    swap(son[x][0],son[x][1]),r[x]^=1;
}
inline void Pushdown(LL x){
    if(r[x]){
        if(son[x][0]) Pushr(son[x][0]);
        if(son[x][1]) Pushr(son[x][1]);
        r[x]=0;
    }
}
inline void Rotate(LL x){
    LL y(fa[x]),z(fa[y]),lz(son[y][1]==x);
    if(Notroot(y)) son[z][son[z][1]==y]=x;fa[x]=z;
    son[y][lz]=son[x][lz^1];
    if(son[y][lz]) fa[son[y][lz]]=y;
    son[x][lz^1]=y; fa[y]=x;
    Update(y),Update(x);
}
inline void Splay(LL x){
    LL y(x),top(0);sta[++top]=y;
    while(Notroot(y)) sta[++top]=y=fa[y];
    while(top) Pushdown(sta[top--]);
    while(Notroot(x)){
        y=fa[x];
        if(Notroot(y)){
            LL z(fa[y]);
            if(((son[y][1]==x)^(son[z][1]==y))==0) Rotate(y);
            else Rotate(x);
        }Rotate(x);
    }
}
inline void Access(LL x){
    for(LL y=0;x;y=x,x=fa[x]){
        Splay(x),isum[x]+=sum[son[x][1]];
        son[x][1]=y;isum[x]-=sum[son[x][1]];
        Update(x);
    }
}
inline void Makeroot(LL x){
    Access(x),Splay(x),Pushr(x);
}
inline void Split(LL x,LL y){
    Makeroot(x),Access(y),Splay(y);
}
inline void Link(LL x,LL y){
    Makeroot(x),Access(y),Splay(y);
    fa[x]=y;
    isum[y]+=sum[x];
    Update(y);
}

LL Get_fa(LL x){
    return f[x]=(f[x]==x?x:Get_fa(f[x]));
}
inline LL Get_w(LL x){
    LL ji=sum[x]&1,M=sum[x]>>1,lsum(0),rsum(0),new_w(inf),nowl,nowr;
    while(x){
        Pushdown(x);
        nowl=sum[son[x][0]]+lsum,nowr=sum[son[x][1]]+rsum;
        if(nowl<=M&&nowr<=M){
            if(ji){
                new_w=x;
                break;
            }else
                new_w=min(new_w,x);
        }
        if(nowl<nowr){
            lsum+=sum[son[x][0]]+isum[x]+1;
            x=son[x][1];
        }else{
            rsum+=sum[son[x][1]]+isum[x]+1;
            x=son[x][0];
        }
    }
    Splay(new_w);
    return new_w;
}
int main(){
    n=Read(),m=Read();
    for(LL i=1;i<=n;++i)
        sum[i]=1,f[i]=i,Xor^=i;
    while(m--){
        char s[100];
        scanf(" %s",s);
        if(s[0]=='X') printf("%d
",Xor);
        else if(s[0]=='Q'){
            LL x(Read());
            printf("%d
",Get_fa(x));
        }else{
            LL x(Read()),y(Read());
            Link(x,y);
            Split(x=Get_fa(x),y=Get_fa(y));
            LL z=Get_w(y);
            f[x]=f[y]=f[z]=z;
            Xor^=x^y^z;
        }
    }return 0;
}

以上是关于P4299 首都的主要内容,如果未能解决你的问题,请参考以下文章

python Python国家代码,名称,大洲,首都和pytz时区列表

Python 爬取 北京市政府首都之窗信件列表-[信息展示]

北京市信件内容爬虫实例——首都之窗

Python 爬取 北京市政府首都之窗信件列表-[后续补充]

Python 爬取 北京市政府首都之窗信件列表-[Scrapy框架](2020年寒假小目标04)

Python 爬取 北京市政府首都之窗信件列表-[数据处理]