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

    我们定义一棵树的删除序列为:每一次将树中编号最小的叶子删掉,将该节点编号加入到当前序列的最末端,最后只剩下一个节点时将该节点的编号加入到结尾。现在给出一棵n个节点的树,有m次操作:

    up v:将v号节点的编号变为当前所有节点编号的(max + 1)

    when v:查询v在当前树的删除序列中是第几号元素

    compare u v:查询u和v在当前树的删除序列中谁更靠前

    题解

    考虑每个点up后会带来什么影响。

    可以发现新修改的这个点和修改这个点之前编号最大的点之间的这条链是最后被删掉的。

    而且删除的顺序是有序的。

    把这条链删掉之后,其他的链之间的删除顺序是不变的。

    所以我们可以考虑维护这些链。

    如果每次令最大的点为根,那么每次的操作相当于是(makeroot)

    这里我们还需要给每条链赋一个权值,为删除顺序当中的优先度,这个可以在(LCT)上打标记。

    还有一个问题就是如何维护一开始的删除序列。

    这个其实(dfs)一遍就可以了,先令每个点的权值为自己的编号,然后自底向上更新,如果儿子的比父亲的大就用儿子去更新父亲。

    代码

    #include<bits/stdc++.h>
    #define N 200009
    #define ls ch[x][0]
    #define rs ch[x][1]
    using namespace std;
    typedef long long ll;
    char s[10];
    int ch[N][2],fa[N],n,q,head[N],tot,size[N],col[N],now,rev[N],maxn;
    inline ll rd(){
    	ll x=0;char c=getchar();bool f=0;
    	while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f?-x:x;
    }
    struct edge{
    	int n,to;
    }e[N<<1];
    struct BIT{
    	int tr[N<<1];
    	inline void add(int x,int y){while(x<=maxn)tr[x]+=y,x+=x&-x;}//!!!!!!!!!!
    	inline int query(int x){int ans=0;while(x)ans+=tr[x],x-=x&-x;return ans;}
    }tr;
    inline bool ge(int x){return ch[fa[x]][1]==x;}
    inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    inline void pushup(int x){size[x]=size[ls]+size[rs]+1;}
    inline void rotate(int x){
    	int y=fa[x],o=ge(x);
    	ch[y][o]=ch[x][o^1];fa[ch[y][o]]=y;
    	if(!isroot(y))ch[fa[y]][ge(y)]=x;fa[x]=fa[y];
    	fa[y]=x;ch[x][o^1]=y;
    	pushup(y);pushup(x);
    }
    inline void pushdown(int x){
    	if(rev[x]){
           rev[ls]^=1;rev[rs]^=1;
           rev[x]^=1;
           swap(ls,rs); 
    	}  
    	if(ls)col[ls]=col[x];///!!!!!
        if(rs)col[rs]=col[x];
    }
    inline void _pushdown(int x){
    	if(!isroot(x))_pushdown(fa[x]);
    	pushdown(x);
    }
    inline void splay(int x){
    	_pushdown(x);
    	while(!isroot(x)){
    		int y=fa[x];
    		if(isroot(y))rotate(x);
    		else rotate(ge(x)==ge(y)?y:x),rotate(x);
    	}
    }
    inline void access(int x){
        for(int y=0;x;y=x,x=fa[x]){
        	splay(x);
            tr.add(col[x],-size[x]+size[rs]);
            tr.add(now,size[x]-size[rs]);
            ch[x][1]=y;pushup(x);
        }
    }
    inline void makeroot(int x){
    	++now;
    	access(x);splay(x);rev[x]^=1;col[x]=now;
    }
    inline void add(int u,int v){
    	e[++tot].n=head[u];e[tot].to=v;head[u]=tot;
    }
    int query(int x){
    	splay(x);
    	return tr.query(col[x]-1)+size[rs]+1;
    }
    void dfs(int u){
    	col[u]=u;
    	size[u]=1;
    	for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa[u]){
    		int v=e[i].to;fa[v]=u;
    		dfs(v);
            if(col[v]>col[u]){
            	col[u]=col[v];
            	ch[u][1]=v;
            	size[u]=size[v]+1;
            }
    	}
    	tr.add(col[u],1);
    }
    int main(){
    	n=rd();q=rd();
    	maxn=n+q;
    	int u,v,w;
    	now=n;
    	for(int i=1;i<n;++i){
    		u=rd();v=rd();
    		add(u,v);add(v,u);
    	}
    	dfs(n);
    	while(q--){
    		scanf("%s",s);
    		if(s[0]=='u'){
              u=rd();
              makeroot(u);
    		}
    		else if(s[0]=='w'){
              u=rd();
              printf("%d
    ",query(u));
    		}
    		else if(s[0]=='c'){
              u=rd();v=rd();
              printf("%d
    ",query(u)>query(v)?v:u);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    解决:Server IPC version 9 cannot communicate with client version 4
    解决Exception: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z
    hadoop解决windows下:Failed to set permissions of path: mp .staging to 0700
    find命令的使用
    linux解决端口冲突问题
    linux中实用的小工具lrzsz
    nginx常用命令
    编写测试用例的方法
    selenium之web自动化模拟操作(窗口,鼠标,键盘,js)
    什么是面向连接服务?什么是无连接服务?它们的区别是什么?
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10882232.html
Copyright © 2011-2022 走看看