bzoj 4573 大森林
bzoj 4573 大森林
- 由于树上路径是唯一的,查询合法的两个点间路径长度显然与其他加点操作无关,所以可以离线处理,将所有的查询放在加点后.
- 这样我们可以对每棵树都在上颗树的基础上处理好形态后,处理这颗树上的询问.
- 考虑若没有操作 \(1\) ,则所有树都一模一样.那么两棵树的形态不同,一定是某一颗执行了操作 \(1\) ,另一个却没有.只需要在每个关键位置(修改开始或结束时)将原来生长点所有子树挂到新的生长点下.
- 若暴力移动子树,当子树数目较大时就会很劣.可以对每个操作 \(1\) 建立一个虚点,将这个操作内挂上去的点都挂在虚点上,于是只需要移动虚点就可以了.注意将虚点 \(siz\) 设置为 \(0\) .
- 查询答案时,使用 \(dep[x]+dep[y]-2*dep[lca]\) 计算,避免虚点造成的影响.
- 直接用 \(split(x,y)\) 会出问题.因为你把路径抠出来之后不知道要不要减去 \(1\) .
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
	int x=0;
	bool pos=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar())
		if(ch=='-')
			pos=0;
	for(;isdigit(ch);ch=getchar())
		x=x*10+ch-'0';
	return pos?x:-x;
}
const int MAXN=3e5+10;
struct query{
	int pos,op,x,y;
	bool operator < (const query &rhs) const
		{
			return pos==rhs.pos?op<rhs.op:pos<rhs.pos;
		}
}q[MAXN];
namespace LCT{
	int stk[MAXN],tp;
	int tot;
	struct node{
		int ch[2],fa;
		int rev;
		int siz,val;
		node()
			{
				fa=ch[0]=ch[1]=0;
				rev=0;
				siz=val=0;
			}
	}tree[MAXN];
	#define root tree[x]
	#define lson tree[root.ch[0]]
	#define rson tree[root.ch[1]]
	inline void pushup(int x)
		{
			root.siz=lson.siz+root.val+rson.siz;
		}
	void inverse(int x)
		{
			swap(root.ch[0],root.ch[1]);
			root.rev^=1;
		}
	void pushdown(int x)
		{
			if(root.rev)
				{
					if(root.ch[0])
						inverse(root.ch[0]);
					if(root.ch[1])
						inverse(root.ch[1]);
					root.rev=0;
				}
		}
	bool isroot(int x)
		{
			int y=root.fa;
			return tree[y].ch[0]!=x && tree[y].ch[1]!=x;
		}
	void rotate(int x)
		{
			int y=tree[x].fa,z=tree[y].fa;
			int k=tree[y].ch[1]==x;
			if(!isroot(y))
				tree[z].ch[tree[z].ch[1]==y]=x;
			tree[x].fa=z;
			tree[tree[x].ch[k^1]].fa=y;
			tree[y].ch[k]=tree[x].ch[k^1];
			tree[x].ch[k^1]=y;
			tree[y].fa=x;
			pushup(y);
			pushup(x);
		}
	void splay(int x)
		{
			tp=0;
			stk[++tp]=x;
			for(int pos=x;!isroot(pos);pos=tree[pos].fa)
				stk[++tp]=tree[pos].fa;
			while(tp)
				pushdown(stk[tp--]);
			while(!isroot(x))
				{
					int y=tree[x].fa,z=tree[y].fa;
					if(!isroot(y))
						(tree[y].ch[0]==x)^(tree[z].ch[0]==y)?rotate(x):rotate(y);
					rotate(x);
				}
			pushup(x);
		}
	int Access(int x)
		{
			int y;
			for(y=0;x;y=x,x=tree[x].fa)
				{
					splay(x);
					tree[x].ch[1]=y;
					pushup(x);
				}
			return y;
		}
	void makeroot(int x)
		{
			Access(x);
			splay(x);
			inverse(x);
		}
	int findroot(int x)
		{
			Access(x);
			splay(x);
			while(tree[x].ch[0])
				x=tree[x].ch[0];
			return x;
		}
	void split(int x,int y)
		{
			makeroot(x);
			Access(y);
			splay(y);
		}
	void Link(int x,int y)
		{
			makeroot(x);
			tree[x].fa=y;
		}
	void Cut(int x)
		{
			Access(x);
			splay(x);
			tree[tree[x].ch[0]].fa=0;
			tree[x].ch[0]=0;
			pushup(x);
		}
}
using namespace LCT;
int solve(int x,int y)
{
	int ans=0;
	Access(x);
	splay(x);
	ans+=tree[x].siz;
	int lca=Access(y);
	splay(y);
	ans+=tree[y].siz;
	Access(lca);
	splay(lca);
	ans-=2*tree[lca].siz;
	return ans;
}
void newnode(int v)
{
	int x=++tot;
	root.val=root.siz=v;
}
int n,m;
int last,id[MAXN],idd,cnt,L[MAXN],R[MAXN],qs;
inline void insq(int pos,int op,int x,int y)
{
	++cnt;
	q[cnt].pos=pos,q[cnt].op=op;
	q[cnt].x=x,q[cnt].y=y;
}
int ans[MAXN];
int main()
{
	tot=0;
	n=read(),m=read();
	newnode(1),idd=1,L[1]=1,R[1]=n,id[1]=1;
	newnode(0),last=2,Link(2,1);
	for(int i=1;i<=m;++i)
		{
			int type=read();
			if(type==0)
				{
					int l=read(),r=read();
					newnode(1);
					L[++idd]=l,R[idd]=r,id[idd]=tot;
					insq(1,i-m,tot,last);
				}
			else if(type==1)
				{
					int l=read(),r=read(),x=read();
					l=max(l,L[x]),r=min(r,R[x]);
					if(l<=r)
						{
							newnode(0);
							Link(tot,last);
							insq(l,i-m,tot,id[x]);
							insq(r+1,i-m,tot,last);
							last=tot;
						}
				}
			else
				{
					int x=read(),u=read(),v=read();
					insq(x,++qs,id[u],id[v]);
				}
		}
	sort(q+1,q+cnt+1);
	for(int i=1,j=1;i<=n;++i)
		{
			for(;j<=cnt && q[i].pos==i;++j)
				{
					if(q[j].op<=0)
						{
							Cut(q[j].x);
							Link(q[j].x,q[j].y);
						}
					else
						ans[q[j].op]=solve(q[j].x,q[j].y);
				}
		}
	for(int i=1;i<=qs;++i)
		printf("%d\n",ans[i]);
	return 0;
}
bzoj 4573 大森林的更多相关文章
- [BZOJ 4573][ZJOI 2016]大森林
		[LOJ 2092][BZOJ 4573][UOJ 195][ZJOI 2016]大森林 题意 给定一个树序列, 初始时所有树都只有一个点, 要求支持三种操作: 区间种树(在某个特定点上长出一个子结点 ... 
- 【刷题】BZOJ 4573 [Zjoi2016]大森林
		Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力.小 ... 
- bzoj 4573: [Zjoi2016]大森林
		Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树 都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. ... 
- BZOJ4573:[ZJOI2016]大森林——题解
		http://www.lydsy.com/JudgeOnline/problem.php?id=4573 https://www.luogu.org/problemnew/show/P3348#sub ... 
- BZOJ 3684 大朋友和多叉树
		BZOJ 3684 大朋友和多叉树 Description 我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树.对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的: ... 
- 「ZJOI2016」大森林 解题报告
		「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ... 
- [ZJOI2016]大森林(LCT)
		题目描述 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. 小Y掌握了一种 ... 
- [ZJOI2016]大森林
		Description: 小Y家里有一个大森林,里面有n棵树,编号从1到n 0 l r 表示将第 l 棵树到第 r 棵树的生长节点下面长出一个子节点,子节点的标号为上一个 0 号操作叶子标号加 1(例 ... 
- [BZOJ 3652]大新闻
		[BZOJ 3652] 大新闻 题意 随机从 \([0,n)\) 中选取一个整数 \(x\), 并从 \([0,n)\) 中再选取一个整数 \(y\). 有 \(p\) 的概率选取一个能令 \(x\o ... 
随机推荐
- C# DES加密,KEY和IV不同设置的写法
			1.KEY和IV分别赋值 //默认密钥向量 private static byte[] Iv= { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; ... 
- php特级课---4、网站服务监控
			php特级课---4.网站服务监控 一.总结 一句话总结:这些是架构师的知识 网络流量监控:cacti,mrtg 邮件报警系统:postfix 压力测试工具:Apache压力测试软件-ab,Mysql ... 
- ABP 学习问题集锦
			一:Update-Database : 无法将“Update-Database”项识别为 cmdlet.函数.脚本文件或可运行程序的名称的问题 解决: 这是因为没有引用EntityFramework命 ... 
- LeetCode 380. Insert Delete GetRandom O(1)
			380. Insert Delete GetRandom O(1) Add to List Description Submission Solutions Total Accepted: 21771 ... 
- BT5 set_config各个选项的配置
			最近研究了一下bt5的社会工程学工具SET,本来国内的bt5的资料就很少了,详细分析SET的资料就更少了,在各大网站找了找,都不靠谱,还是得自力更生啊,我在这里就把自己的过程写下来,希望对大家有点帮助 ... 
- SPOJ BALNUM ★(位压缩状态+数位DP)
			题意 求区间[A,B]上的平衡数个数.平衡数是这样的数:在数的各个位上,奇数数字出现偶数次,偶数数字出现奇数次. 思路 很明显我们需要记录每一位出现的次数.分别记录是不明智的,而我们又只需要记录奇数次 ... 
- Centos7 Erlang Solutions 安装
			https://www.erlang-solutions.com/resources/download.html Installation using repository 1. Adding rep ... 
- 【Error】 : make 不是内部或外部命令,也不是可运行的程序
			之前有段源码需要编译,一开始选择在Windows上编译,由于没有安装VS,只能采取Make + Gcc 的方式,虽然后来还是在ubuntu上编译的,但是遇到的问题还是要记录下来. 虽然我也把make的 ... 
- 伪基站,卒于5G——本质上是基于网络和UE辅助的伪基站检测,就是将相邻基站的CI、信号强度等信息通过测量报告上报给网络,网络结合网络拓扑、配置信息等相关数据,对所有数据进行综合分析,确认在某个区域中是否存在伪基站
			伪基站,卒于5G from:https://www.huxiu.com/article/251252.html?h_s=h8 2018-07-05 21:58收藏27评论6社交通讯 本文来自微 ... 
- RxJava 中的Map函数原理分析
			首先看一段Map函数的使用代码: Observable.create(new Observable.OnSubscribe<Integer>() { @Override public vo ... 
