zoukankan      html  css  js  c++  java
  • P4219 [BJOI2014]大融合 LCT维护子树信息

    题意:

    戳这里

    分析:

    我们发现题意就是求一条边所连两个点各自的子树大小的乘积

    但是关键问题来了,LCT 的本质是维护链的信息,那么怎么维护子树的信息呢?

    常见操作就是新开一个数组用来记录子树信息( (siz,val) 等)

    但是在 (link,access,cut) 这类修改 (splay) 形态的操作中,我们需要手动更改实虚儿子变化带来的影响,然后让影响 (pushup) 上去就可以了

    • tip: (link) 里面原来的 (makeroot) 需要改成 (split) (等价于 (makeroot,access,splay)) 因为需要修改对 (y) 的影响所以要把 (y) 旋上去

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
    	int read()
    	{
    		int x=0,f=1;char ch=getchar();
    		while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    		while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    		return x*f;
    	}
    	const int maxn = 1e5+5;
    	int n,m,a,b;
    	char opt[5];
    	namespace lct
    	{
    		int top,q[maxn],c[maxn][2],fa[maxn],siz[maxn],rev[maxn],val[maxn];
    		void pushup(int x){siz[x]=siz[c[x][0]]+siz[c[x][1]]+val[x]+1;}
    		void pushdown(int x)
    		{
    			int l=c[x][0],r=c[x][1];
    			if(rev[x])
    			{
    				rev[l]^=1;rev[r]^=1;rev[x]^=1;
    				swap(c[x][0],c[x][1]);
    			}
    		}
    		bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
    		void rotate(int x)
    		{
    			int y=fa[x],z=fa[y],l,r;
    			if(c[y][0]==x)l=0;else l=1;r=l^1;
    			if(!isroot(y)){if(c[z][0]==y)c[z][0]=x;else c[z][1]=x;}
    			fa[y]=x;fa[x]=z;fa[c[x][r]]=y;
    			c[y][l]=c[x][r];c[x][r]=y;
    			pushup(y);pushup(x);
    		}
    		void splay(int x)
    		{
    			top=1;q[top]=x;
    			for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
    			for(int i=top;i;i--) pushdown(q[i]);
    			while(!isroot(x))
    			{
    				int y=fa[x],z=fa[y];
    				if(!isroot(y))
    				{
    					if((c[z][0]==y)^(c[y][0]==x)) rotate(x);
    					else rotate(y);
    				}
    				rotate(x);
    			}
    		}
    		void access(int x){for(int t=0;x;t=x,x=fa[x])splay(x),val[x]+=siz[c[x][1]]-siz[c[x][1]=t],pushup(x);}
    		void makeroot(int x){access(x);splay(x);rev[x]^=1;}
    		int find(int x){access(x);splay(x);while(c[x][0])x=c[x][0];splay(x);return x;}
    		void split(int x,int y){makeroot(x);access(y);splay(y);}
    		void cut(int x,int y){split(x,y);if(c[y][0]==x&&c[x][1]==0)fa[x]=0,c[y][0]=0,pushup(y);}
    		void link(int x,int y){split(x,y);fa[x]=y;val[y]+=siz[x];pushup(y);}
    	}
    	using namespace lct;
    	
    	void work()
    	{
    		n=read();m=read();
    		for(int i=1;i<=m;i++)
    		{
    			scanf("%s",opt);a=read();b=read();
    			if(opt[0]=='A') link(a,b);
    			else
    			{
    				split(a,b);
    				printf("%lld
    ",1ll*(val[a]+1)*(val[b]+1));
    			}
    		}
    	}
    	
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
  • 相关阅读:
    C# WPF开源控件库MaterialDesign介绍
    C# MQTT 服务端客户端通讯
    C#串口调试工具 (WPF/MVVM结构完整示例版)
    WPF转换器
    WPF动画基础及实例
    WPF MVVM架构 EF、WCF、IOC 设计示例经典
    SpringMVC中采用简洁的配置实现文件上传
    Maven 默认 SpringMVC-servlet.xml 基本配置
    maven pom.xml基本设置
    maven pom.xml设置jdk编译版本为1.8
  • 原文地址:https://www.cnblogs.com/youth518/p/14111504.html
Copyright © 2011-2022 走看看