[CF1528C]Trees of Tranquillity

Posted Tan_tan_tann

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1528C]Trees of Tranquillity相关的知识,希望对你有一定的参考价值。

Trees of Tranquillity

题解

(可以略过)

First and foremost,我们需要理解clique的概念,它的意思是一个完全联通的子图。虽然我并不认为会有像我一样将它理解成联通块,然后yy了半天的魔鬼4个优先队列+权值线段树的人

如果理解了clique的概念,我们很容易发现,符合要求的点集中的点一定分布在同一条从根开始的链上。
于是,我们可以对于从根到一个叶子节点的路径上,考虑如何从中选出最多的在另一棵树上没有祖先关系的点集来。

考虑如何维护另一棵树上的祖先关系,我们可以先将其转化成 d f n dfn dfn序列上的区间包含关系。
由于对于任意一个节点,它子孙的 d f n dfn dfn区间一定被包含在其的 d f n dfn dfn之内,所以我们相当于选出数量最多的没有包含关系的区间。
由于 d f n dfn dfn序的区间并不存在相交关系,所以我们很容易得到一种贪心做法。
假设 1 − > f a u 1->fa_{u} 1>fau的路径上最优的区间集合为 S S S,如果 u u u的区间与 S S S中的区间没有包含关系,就直接将其加进去,否则保留长度更小的那个区间。
因为与长度较小的区间有包含关系的区间一定与另一个较大的区间有包含关系,反之不然,所以这样做一定是最优的。
于是我们可以通过线段树来维护最优的点集,然后通过可持久化或者撤回操作来枚举第一棵树上的点,得到最优点集的最大值。

时间复杂度 O ( n l o g   n ) O\\left(nlog\\,n\\right) O(nlogn)

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 300005
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=0x7f7f7f7f7f7f7f7f;
const int mo=998244353;
const int zero=500;
const LL jzm=2333;
const int iv2=499122177;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int n,t,ans,cnt,pre[MAXN];
struct edge{int to,nxt;};
class SegmentTree{
	private:
		int tr[MAXN<<2];
	public:
		void insert(int rt,int l,int r,int ai,int aw){
			if(l>ai||r<ai||l>r)return ;int mid=l+r>>1;
			if(l==r){tr[rt]=aw;return ;}
			if(ai<=mid)insert(rt<<1,l,mid,ai,aw);
			if(ai>mid)insert(rt<<1|1,mid+1,r,ai,aw);
			tr[rt]=max(tr[rt<<1],tr[rt<<1|1]);
		}
		int query(int rt,int l,int r,int aw){
			if(tr[rt]<aw)return n+1;if(l==r)return l;int mid=l+r>>1;
			if(tr[rt<<1]>=aw)return query(rt<<1,l,mid,aw);
			return query(rt<<1|1,mid+1,r,aw);
		}
		void build(int rt,int l,int r){
			tr[rt]=0;if(l==r)return ;int mid=l+r>>1;
			build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
		}
}T;
class Tree{
	public:
		int tot,head[MAXN],dfn[MAXN],ld[MAXN],rd[MAXN],idx;edge e[MAXN<<1];
		void addEdge(int u,int v){e[++tot]=(edge){v,head[u]};head[u]=tot;}
		void dosaka(int u,int fa){
			dfn[u]=++idx;ld[u]=idx;
			for(int i=head[u];i;i=e[i].nxt)
				if(e[i].to!=fa)dosaka(e[i].to,u);
			rd[u]=idx;
		}
		void clear(){tot=idx=0;for(int i=1;i<=n;i++)head[i]=dfn[i]=ld[i]=rd[i]=0;}
}T1,T2;
void dfs(int u,int fa){
	int tmp=T.query(1,1,n,T2.ld[u]),del=0,las=cnt;bool ins=0;
	if(tmp<=T2.rd[u]){
		if(T2.ld[pre[tmp]]<=T2.ld[u])
			T.insert(1,1,n,T2.ld[pre[tmp]],0),del=pre[tmp],pre[tmp]=0,
			pre[T2.ld[u]]=u,T.insert(1,1,n,T2.ld[u],T2.rd[u]),ins=1;
	}
	else T.insert(1,1,n,T2.ld[u],T2.rd[u]),pre[T2.ld[u]]=u,cnt++,ins=1;
	ans=max(ans,cnt);for(int i=T1.head[u];i;i=T1.e[i].nxt)if(T1.e[i].to!=fa)dfs(T1.e[i].to,u);
	cnt=las;if(ins)pre[T2.ld[u]]=0,T.insert(1,1,n,T2.ld[u],0);
	if(del)pre[T2.ld[del]]=del,T.insert(1,1,n,T2.ld[del],T2.rd[del]);
}
signed main(){
	read(t);
	while(t--){
		read(n);ans=1;T.build(1,1,n);
		for(int i=2,p;i<=n;i++)read(p),T1.addEdge(i,p),T1.addEdge(p,i);
		for(int i=2,p;i<=n;i++)read(p),T2.addEdge(i,p),T2.addEdge(p,i);
		T1.dosaka(1,0);T2.dosaka(1,0);dfs(1,0);
		printf("%d\\n",ans);T1.clear();T2.clear();
	}
	return 0;
}

谢谢!!!

以上是关于[CF1528C]Trees of Tranquillity的主要内容,如果未能解决你的问题,请参考以下文章

CF276E Little Girl and Problem on Trees 题解

CF917D Stranger Trees

CF58C Trees(逆向思维)

CF1304E 1-Trees and Queries

CF917D Stranger Trees

CF917D Stranger Trees