zoukankan      html  css  js  c++  java
  • CF1137F Matches Are Not a Child's Play

    CF1137F Matches Are Not a Child's Play 

    trick题目

    考虑变成有根树,把最后删除的点当做根

    就是n了

    发现,up操作就是换根!

    如果不换根?

    直接求出序列查询即可

    换根?

    那么,新根y是最大值,原根x是次大值,

    那么一定是把其他的点都直接删掉,最后剩下(x,y)路径的点,从x一路删到y

    发现对于其他点删除的相对顺序不变

    我们给(x,y)的路径打一个时间戳mx+1也就是当前最大权值+1

    开始i的时间戳就是i的初始排名

    那么一个点u的排名一定就是:

    时间戳小于u的个数+u子树内时间戳和u一样的数

    后者一定是一段连接u的链

    并且我们发现,同一个时间戳一定连成的一个链,不会断开

    这其实就是access!,再修改颜色

    LCT进行换根,树状数组维护时间戳为x的数的个数

    access换颜色的时候打标记,并且更新树状数组

    注意rotate是nrt(y)

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int N=200000+5;
    int n,m;
    int lim;
    struct edge{
        int nxt,to;
    }e[2*N];
    int hd[N],cnt;
    priority_queue<int,vector<int>,greater<int> >q;
    void link(int x,int y){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        hd[x]=cnt;
    }
    int f[2*N];
    void add(int x,int c){
        for(;x<=lim;x+=x&(-x)) f[x]+=c;
    }
    int query(int x){
        int ret=0;
        for(;x;x-=x&(-x)) ret+=f[x];
        return ret;
    }
    struct node{
        int ch[2],fa;
        int rev,tim;
        int tag;
        int sz;
        void op(){
            cout<<" ch[0] "<<ch[0]<<" ch[1] "<<ch[1]<<" fa "<<fa<<endl;
        }
    }t[N];
    int du[N];
    void dfs(int x,int fa){
        t[x].sz=1;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(y==fa) continue;
            t[y].fa=x;
            dfs(y,x);
        }
    }
    #define ls t[x].ch[0]
    #define rs t[x].ch[1]
    bool nrt(int x){
        return (t[t[x].fa].ch[0]==x||t[t[x].fa].ch[1]==x);
    }
    void pushup(int x){
        if(x) t[x].sz=t[ls].sz+t[rs].sz+1;
    }
    void tag(int x,int c){
        t[x].tag=c;
        t[x].tim=c;
    }
    void rev(int x){
        t[x].rev^=1;
        swap(ls,rs);
    }
    void pushdown(int x){
        if(t[x].rev){
            rev(ls);rev(rs);
            t[x].rev=0;
        }
        if(t[x].tag){
            tag(ls,t[x].tag);tag(rs,t[x].tag);
            t[x].tag=0;
        }
    }
    void rotate(int x){
        int y=t[x].fa,d=t[y].ch[1]==x;
        t[t[y].ch[d]=t[x].ch[!d]].fa=y;
        if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x;
        else t[x].fa=t[y].fa;
        t[t[x].ch[!d]=y].fa=x;
        pushup(y);
    }
    int sta[N];
    void splay(int x){
        int y=x,z=0;
        sta[++z]=y;
        while(nrt(y)) y=t[y].fa,sta[++z]=y;
        while(z) pushdown(sta[z--]);
    
        while(nrt(x)){
            y=t[x].fa,z=t[y].fa;
            if(nrt(y)){
                rotate((t[y].ch[0]==x)==(t[z].ch[0]==y)?y:x);
            }
            rotate(x);
        }
        pushup(x);
    }
    void access(int x,int c){
        for(reg y=0;x;y=x,x=t[x].fa){
            splay(x);
            add(t[x].tim,-t[ls].sz-1);
            add(c,t[ls].sz+1);
            t[x].ch[1]=y;
            tag(x,c);
            pushup(x);
        }
    }
    void makert(int x,int c){
        access(x,c);splay(x);rev(x);
    }
    int rk(int x){
        splay(x);
        int ret=t[rs].sz+query(t[x].tim-1)+1;
        return ret;
    }
    int main(){
        rd(n);rd(m);
        lim=n+m;
        int x,y;
        int rt=n;
        for(reg i=1;i<n;++i){
            rd(x);rd(y);
            ++du[x];++du[y];
            link(x,y);link(y,x);
        }
        for(reg i=1;i<=n;++i) if(du[i]==1) q.push(i);
        int df=0;
        while(!q.empty()){
            int x=q.top();q.pop();
            t[x].tim=++df;
            add(df,1);
            for(reg i=hd[x];i;i=e[i].nxt){
                int y=e[i].to;
                if(du[y]>1){
                    --du[y];
                    if(du[y]==1) q.push(y);
                }
            }
        }
        dfs(rt,0);
        char s[233];
        while(m--){
            scanf("%s",s+1);
            if(s[1]=='u'){
                ++df;
                rd(x);
                makert(x,df);
            }else if(s[1]=='w'){
                rd(x);printf("%d
    ",rk(x));
            }else{
                rd(x);rd(y);
                int A=rk(x),B=rk(y);
                printf("%d
    ",A<B?x:y);
            }
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */

    考虑提出来根,然后就是换根

    考虑换根对路径(x,y)的影响,发现时间戳很合适!

    然后LCTaccess

  • 相关阅读:
    MogoDb的使用及配置
    HttpClient中转上传文件
    springboot +Thymeleaf+UEditor整合记录
    Linux 下安装mysql
    Java开发微信公众号(五)---微信开发中如何获取access_token以及缓存access_token
    Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理
    Java开发微信公众号(三)---微信服务器请求消息,响应消息,事件消息以及工具处理类的封装
    Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发
    Java开发微信公众号(一)---初识微信公众号以及环境搭建
    mybatis sql转义符号
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10871586.html
Copyright © 2011-2022 走看看