zoukankan      html  css  js  c++  java
  • QTREE5 Link-Cut Tree

    (Problem Link)

    题目大意

    你被给定一棵n个点的树,点从1到n编号。每个点可能有两种颜色:黑或白。我们定义dist(a,b)为点a至点b路径上的边个数。

    一开始所有的点都是黑色的。

    要求作以下操作:

    0 i 将点i的颜色反转(黑变白,白变黑)

    1 v 询问dist(u,v)的最小值。u点必须为白色(u与v可以相同),显然如果v是白点,查询得到的值一定是0。

    特别地,如果作'1'操作时树上没有白点,输出-1.

    思想分析

    这题的动态点分治做法看我的总结

    这题动态点分治做法还挺简单的,但是LCT做法就复杂一些,不过总体来说还是板子

    我们定义(lmn[x],rmn[x])分别代表在(splay)(x)的子树里深度最浅的点能够到达最近的白点的距离,

    和深度最深的点能够到达最近的白点的距离

    还要开个堆或者(multiset)维护一下子树中的(lmn)最小值.

    这道题询问的是点到最近的白点的距离,所以就不需要维护子树信息了

    不需要拉链,也就不用split,makert,findrt等一大堆操作了

    这个时候LCT还是跑的很快的,比动态点分治快了一倍(qwq)

    代码实现

    /*
    @Date    : 2019-09-10 17:14:38
    @Author  : Adscn (adscn@qq.com)
    @Link    : https://www.cnblogs.com/LLCSBlog
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define IL inline
    #define RG register
    #define gi getint()
    #define gc getchar()
    #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    template<typename T>IL bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
    template<typename T>IL bool chkmin(T &x,const T &y){return x>y?x=y,1:0;}
    IL int getint()
    {
    	RG int xi=0;
    	RG char ch=gc;
    	bool f=0;
    	while(!isdigit(ch))ch=='-'?f=1:f,ch=gc;
    	while(isdigit(ch))xi=xi*10+ch-48,ch=gc;
    	return f?-xi:xi;
    }
    template<typename T>
    IL void pi(T k,char ch=0)
    {
    	if(k<0)k=-k,putchar('-');
    	if(k>=10)pi(k/10,0);
    	putchar(k%10+'0');
    	if(ch)putchar(ch);
    }
    const int N=1e5+7;
    const int inf=1e9;
    int n;
    namespace LCT{
    	int fa[N],ch[N][2],lmn[N],rmn[N],siz[N],col[N];
    	multiset<int>s[N];
    	multiset<int>::iterator it;
    	#define ls(x) (ch[x][0])
    	#define rs(x) (ch[x][1])
    	#define s(x,k) (ch[x][k])
    	inline bool ws(int x,int p){return rs(p)==x;}
    	inline bool nrt(int x){return ls(fa[x])==x||rs(fa[x])==x;}
    	inline int fir(int x){return s[x].empty()?inf:*s[x].begin();}
    	inline void pushup(int x){
    		if(!x)return;
    		siz[x]=siz[ls(x)]+siz[rs(x)]+1;
    		lmn[x]=min(lmn[ls(x)],siz[ls(x)]+min(col[x]?0:inf,min(fir(x),lmn[rs(x)])+1));
    		rmn[x]=min(rmn[rs(x)],siz[rs(x)]+min(col[x]?0:inf,min(fir(x),rmn[ls(x)])+1));
    	}
    	inline void rotate(int x){
    		int p=fa[x],g=fa[p];
    		int t=ws(x,p),w=s(x,!t);
    		if(nrt(p))s(g,ws(p,g))=x;s(x,!t)=p;s(p,t)=w;
    		if(w)fa[w]=p;fa[p]=x;fa[x]=g;
    		pushup(p);
    	}
    	inline void Splay(int x){
    		while(nrt(x))
    		{
    			int p=fa[x],g=fa[p];
    			if(nrt(p))rotate(ws(x,p)^ws(p,g)?x:p);
    			rotate(x);
    		}
    		pushup(x);
    	}
    	inline void access(int x){
    		for(int y=0;x;x=fa[y=x])
    		{
    			Splay(x);
    			s[x].insert(lmn[rs(x)]);
    			if((it=s[x].lower_bound(lmn[y]))!=s[x].end())s[x].erase(it);
    			rs(x)=y,pushup(x);
    		}
    	}
    	inline void modify(int x){
    		access(x),Splay(x);
    		col[x]^=1;
    		pushup(x);
    	}
    	inline int query(int x){
    		access(x);Splay(x);
    		return rmn[x]>n?-1:rmn[x];
    	}
    }
    using namespace LCT;
    struct edge{
    	int v,nxt;
    }e[N<<1|1];
    int head[N],cnt;
    inline void add(int u,int v){e[++cnt]=(edge){v,head[u]},head[u]=cnt;}
    inline void init(){memset(head,cnt=-1,sizeof head);}
    inline void dfs(int x,int p)
    {
    	for(int i=head[x],v;~i;i=e[i].nxt)
    		if((v=e[i].v)^p)
    			fa[v]=x,dfs(v,x);
    }
    int main(void)
    {
    	n=gi,lmn[0]=rmn[0]=inf;
    	init();
    	for(int i=1,u,v;i<n;++i)u=gi,v=gi,add(u,v),add(v,u);
    	dfs(1,0);
    	for(int i=1,m=gi;i<=m;++i)
    	{
    		int opt=gi,x=gi;
    		if(opt^1)modify(x);
    		else pi(query(x),'
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    Roce ofed 环境搭建与测试
    Ubuntu 1804 搭建NFS服务器
    Redhat 8.0.0 安装与网络配置
    Centos 8.1 安装与网络配置
    SUSE 15.1 系统安装
    VSpare ESXi 7.0 基本使用(模板、iso、SRIOV)
    VSpare ESXi 7.0 服务器安装
    open SUSE leap 15.1 安装图解
    KVM虚拟机网卡连接网桥
    GitHub Action一键部署配置,值得拥有
  • 原文地址:https://www.cnblogs.com/LLCSBlog/p/11511132.html
Copyright © 2011-2022 走看看