CF1137F Matches Are Not a Child's Play(LCT思维题)

时间:2019-04-20
本文章向大家介绍CF1137F Matches Are Not a Child's Play(LCT思维题),主要包括CF1137F Matches Are Not a Child's Play(LCT思维题)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目

CF1137F
很有意思的题目

做法

直接考虑带修改的做法,上一次最大值为u,这次修改v,则最大值为v了
我们发现:\(u-v\)这条链会留到最后,序列里的其他元素相对位置不变,这条链会\(u\longrightarrow v\)排到最后
序列会分成很多块,而这些块是以链为基础的

可以用\(LCT\)来做,具体说一下:
最大值放到根,修改v,就把\(v\)换成根,这个时候会拉一条链\(u-v\),此时\(u\)\(v\)的右子树,\(x\)在单个块中的排序,就是\(LCT\)里单个\(splay\)\(x\)大的数量\(+1\)
\(splay\)外的个数,就是其他块的总和,每条链用一个时间轴\(tim\)记录,在换根的时候就会变化经过的每条链的大小

考虑带修前缀和,用树状数组维护

Code

#include<bits/stdc++.h>
typedef int LL;
const LL maxn=1e6+9;
void Dfs(LL u,LL f);
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;
}
struct node{
    LL to,nxt;
}dis[maxn];
LL num,tim;
LL head[maxn];
inline void Add(LL u,LL v){
    dis[++num]=(node){v,head[u]}; head[u]=num;
}
struct BIT{
    LL up;
    LL tree[maxn];
    inline LL Lowbit(LL x){
        return x&-x;
    }
    inline void Add(LL x,LL val){
        for(x;x<=up;x+=Lowbit(x)) tree[x]+=val;
    }
    inline LL Query(LL x){
        LL ret(0);
        for(;x;x-=Lowbit(x)) ret+=tree[x];
        return ret;
    }
}t1;
struct LCT{
    LL fa[maxn],son[maxn][2],size[maxn],lazy[maxn],r[maxn],col[maxn],sta[maxn];
    inline LL N_rt(LL x){
        return son[fa[x]][0]==x||son[fa[x]][1]==x;
    }
    inline void Up(LL x){
        size[x]=size[son[x][0]]+size[son[x][1]]+1;
    }
    inline void Ro(LL x){
        LL y(fa[x]),z(fa[y]),lz(son[y][1]==x);
        if(N_rt(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;
        Up(y); Up(x);
    }
    inline void Pr(LL x){
        std::swap(son[x][0],son[x][1]); r[x]^=1;
    }
    inline void Pd(LL x){
        LL lc(son[x][0]),rc(son[x][1]);
        if(r[x]){
            if(lc) Pr(lc);
            if(rc) Pr(rc);
            r[x]=0;
        }
        if(lazy[x]){
            if(lc) col[lc]=lazy[lc]=lazy[x];
            if(rc) col[rc]=lazy[rc]=lazy[x];
            lazy[x]=0;
        }
    }
    inline void Splay(LL x){
        LL top(0),y(x); sta[++top]=y;
        while(N_rt(y)) y=fa[y],sta[++top]=y;
        while(top) Pd(sta[top--]);
        while(N_rt(x)){
            y=fa[x];
            if(N_rt(y)){
                LL z(fa[y]);
                if((son[y][1]==x)^(son[z][1]==y)) Ro(x);else Ro(y);
            }Ro(x);
        }
    }
    inline void Ac(LL x,LL id){
        LL y(0);
        for(;x;y=x,x=fa[x]){
            Splay(x); LL z(son[x][1]);
            t1.Add(col[x],size[z]-size[x]);
            son[x][1]=y;
            Up(x);
        }
        t1.Add(id,size[y]); lazy[y]=id; col[y]=id;
    }
    inline void Mk_rt(LL x,LL id){
        Ac(x,id); Splay(x); Pr(x);
    }
    inline LL Query(LL u){
        Splay(u); LL ret(t1.Query(col[u]-1));
        ret+=size[son[u][1]]+1;
        return ret;
    }
}t2;
LL n,m;
char s[maxn];
int main(){
    n=Read(); m=Read();
    for(LL i=1;i<n;++i){
        LL u(Read()),v(Read());
        Add(u,v); Add(v,u);
    }
    Dfs(1,0);
    t1.up=(n<<1)+m;
    for(LL i=1;i<=n;++i){
        t2.col[i]=i; t2.size[i]=1;
        t1.Add(i,1);
    }
    tim=n;
    for(LL i=1;i<=n;++i)
        t2.Mk_rt(i,++tim);
    while(m--){
        scanf(" %s",s+1); LL u,v;
        if(s[1]=='u'){
            u=Read();
            t2.Mk_rt(u,++tim);
        }else if(s[1]=='w'){
            u=Read();
            printf("%d\n",t2.Query(u));
        }else{
            u=Read(); v=Read();
            printf("%d\n",t2.Query(u)<t2.Query(v)?u:v);
        }
    }
}
void Dfs(LL u,LL f){
    for(LL i=head[u];i;i=dis[i].nxt){
        LL v(dis[i].to); if(v==f) continue;
        Dfs(v,u);
        t2.fa[v]=u;
    }
}