zoukankan      html  css  js  c++  java
  • CF1137F Matches Are Not a Child's Play(LCT思维题)

    题目

    CF1137F
    很有意思的题目

    做法

    直接考虑带修改的做法,上一次最大值为u,这次修改v,则最大值为v了
    我们发现:(u-v)这条链会留到最后,序列里的其他元素相对位置不变,这条链会(ulongrightarrow 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
    ",t2.Query(u));
    		}else{
    			u=Read(); v=Read();
    			printf("%d
    ",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;
    	}
    }
    
  • 相关阅读:
    继承与多态
    String作业
    课后作业及动手动脑
    作业3
    动手动脑
    实验任务四
    动手动脑
    课堂练习01
    《大道至简》第一章读后感伪代码
    C++常用编程关键字
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10740133.html
Copyright © 2011-2022 走看看