CF1527D MEX Tree(mex&树&容斥)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1527D MEX Tree(mex&树&容斥)相关的知识,希望对你有一定的参考价值。

CF1527D MEX Tree(mex&树&容斥)

考虑简单容斥, m e x i mex_i mexi 等于包含 [ 0 , i − 1 ] [0,i-1] [0,i1]的所有路径减取包含 [ 0 , i ] [0,i] [0,i]的路径。

记录: a n s i ans_i ansi为包含 [ 0 , i ] [0,i] [0,i]的所有路径。

m e x i = a n s i − 1 − a n s i mex_i=ans_i-1-ans_i mexi=ansi1ansi

m e x 0 = n ( n − 1 ) 2 − a n s 0 mex_0=\\dfracn(n-1)2-ans_0 mex0=2n(n1)ans0

转化为求 a n s i ans_i ansi

考虑从小到大递推。

当前包含 [ 0 , i − 1 ] [0,i-1] [0,i1]的最短路径端点为 l , r l,r l,r

情况1 i i i l , r l,r l,r路径上,不用操作。

情况2 i i i l l l r r r的子树结点,将 l l l r r r移动到 i i i上,答案就是两个子树大小的乘积。

情况3 i i i不是 l , r l,r l,r的两个 l c a lca lca,说明无解,直接break,后面的 i i i都无解。

注意当 l = 1 l=1 l=1 r = 1 r=1 r=1 要减取对方的子树大小,再乘积。

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

#include<bits/stdc++.h>
using namespace std;
#define ri register int
typedef long long ll;
const int maxn=2e5+10;
struct node
	int to,nxt;
e[maxn<<1];
int hd[maxn],len;
inline void addedge(int fr,int to)
	e[++len]=to,hd[fr];
	hd[fr]=len;

int dep[maxn],fa[maxn],n,son[maxn],t,top[maxn];
ll siz[maxn];
void dfs1(int p,int f)
	dep[p]=dep[f]+1;
	fa[p]=f;
	siz[p]=1;
	for(ri i=hd[p];i;i=e[i].nxt)
		if(e[i].to!=f)
			dfs1(e[i].to,p);
			siz[p]+=siz[e[i].to];
			if(siz[e[i].to]>siz[son[p]])son[p]=e[i].to;
		

void dfs2(int p,int k)
	top[p]=k;
	if(son[p])
		dfs2(son[p],k);
		for(ri i=hd[p];i;i=e[i].nxt)
			if(!top[e[i].to])
				dfs2(e[i].to,e[i].to);
	

inline int lca(int x,int y)
	while(top[x]!=top[y])
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		x=fa[top[x]];
	
	return dep[x]<dep[y]?x:y;

ll ans[maxn];
int main()
	scanf("%d",&t);
	while(t--)
		scanf("%d",&n);
		len=0;
		memset(hd,0,sizeof hd);
		memset(son,0,sizeof son);
		memset(top,0,sizeof top);
		for(ri i=1,x,y;i<n;++i)
			scanf("%d%d",&x,&y),++x,++y;
			addedge(x,y),addedge(y,x);
		
		dfs1(1,0);
		dfs2(1,1);
		memset(ans,0,sizeof ans);
		ll sum=1;
		for(ri i=hd[1];i;i=e[i].nxt)ans[1]+=siz[e[i].to]*sum,sum+=siz[e[i].to];
		printf("%lld",1ll*n*(n-1)/2-ans[1]);
		ri l=1,r=1,sl,sr;
		for(ri i=2;i<=n;++i)
			ri a=lca(i,l),b=lca(i,r);
			if(a==l&&b==1)
				if(l==1)
					sl=siz[i];
					for(ri j=i;fa[j]>1;j=fa[j],sl=siz[j]);
				
				l=i;
			
			else if(b==r&&a==1)
				if(r==1)
					sr=siz[i];
					for(ri j=i;fa[j]>1;j=fa[j],sr=siz[j]);
				
				r=i;
			
			else if(a!=i&&b!=i)break;
			if(l==1)ans[i]=siz[r]*(n-sr);
			else if(r==1)ans[i]=siz[l]*(n-sl);
			else ans[i]=siz[l]*siz[r];
		
		for(ri i=2;i<=n+1;++i)printf(" %lld",ans[i-1]-ans[i]);
		printf("\\n");
	
	return 0;

以上是关于CF1527D MEX Tree(mex&树&容斥)的主要内容,如果未能解决你的问题,请参考以下文章

线段树CF1083C Max Mex

[CF817F]MEX Queries

[CF1083C]Max Mex

思维题(取模)| CF#615Div3 D.MEX maximizing

CF1083C Max Mex(线段树上二分)

CF1083C Max Mex 线段树