当前位置: 首页 > news >正文

CF1740H MEX Tree Manipulation

题目描述

有一棵不断加叶子的树,叶子的权值是0,其余节点的权值是其子节点的 mex \texttt{mex} mex

  • mex \texttt{mex} mex定义为最小的没有出现过的自然数。

解题思路

首先离线建树,把树做轻重链剖分。

对于一个节点 u u u,设其轻儿子中最小的没有出现能过的自然数是 A A A,次小的是 B B B,其重儿子权值是 x x x

  • x = A x=A x=A,则 v ( u ) = B v(u)=B v(u)=B

  • x ≠ A x\neq A x=A,则 v ( u ) = A v(u)=A v(u)=A

我们可以用一个五元组 ( v , A , B , X , Y ) (v,A,B,X,Y) (v,A,B,X,Y)来描述这样的信息:

  • x = v x=v x=v,则返回的是 A A A,权值和会加上 X X X

  • x ≠ v x\neq v x=v,则返回的是 B B B,权值和会加上 Y Y Y

观察到这样的信息是可以合并的,因此我们用线段树维护一条重链的信息。

修改和普通动态 d p dp dp的修改是类似的

有一个小细节是一个点的权值是 O ( log ⁡ n ) O(\log n) O(logn)的,因此可以用数组存储每个点轻子树的点权,方便求出 A , B A,B A,B

复杂度 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+7;
typedef long long LL; 
struct Info
{
	int x;
	int A1,A2;
	LL S1,S2; 
	Info(){x=A1=A2=S1=S2=-1;}
	Info(int a,int b,LL c,int d,LL e){x=a;A1=b;S1=c;A2=d;S2=e;}
};
inline void process(int &v,LL &w,Info U)
{
	if(v==U.x) 
	{
		v=U.A1;
		w+=U.S1;
	}
	else
	{
		v=U.A2;
		w+=U.S2;
	}
}
Info Push(Info A,Info B)
{
	if(A.x==-1)return B;
	Info C;
	C.x=A.x;
	int v;LL w;
	v=A.A1,w=A.S1;process(v,w,B);C.A1=v;C.S1=w;
	v=A.A2;w=A.S2;process(v,w,B);C.A2=v;C.S2=w; 
	return C;
}
int n;
struct edge
{
	int y,next;
}e[2*N];
int link[N],t=0;
void add(int x,int y)
{
	e[++t].y=y;
	e[t].next=link[x];
	link[x]=t;
}
int siz[N],top[N],son[N],dfn[N],timer=0;
int fa[N],st[N],ed[N];
void dfs(int x,int pre)
{
	siz[x]=1;fa[x]=pre;
	for(int i=link[x];i;i=e[i].next)
	{
		int y=e[i].y;
		if(y==pre)continue;
		dfs(y,x);
		siz[x]+=siz[y];
		if(siz[y]>siz[son[x]])son[x]=y;
	}
}
void Exdfs(int x,int topth)
{
	top[x]=topth;
	dfn[x]=++timer;
	if(x==topth) st[x]=dfn[x];
	ed[top[x]]=dfn[x];
//	cout<<x<<' '<<topth<<' '<<st[topth]<<' '<<ed[topth]<<endl;
	if(!son[x])return;
	Exdfs(son[x],topth);
	for(int i=link[x];i;i=e[i].next)
	{
		int y=e[i].y;
		if(y==fa[x]||y==son[x])continue;
		Exdfs(y,y);
	}
}
Info tr[N*4];
void update(int k,int l,int r,int x,Info U)
{
//	cout<<"update:"<<x<<endl;
	if(l==r)
	{
		tr[k]=U;
//	cout<<l<<' '<<r<<' '<<tr[k].x<<' '<<tr[k].A1<<' '<<tr[k].A2<<' '<<tr[k].S1<<' '<<tr[k].S2<<endl;
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid) update(k<<1,l,mid,x,U);
	else update(k<<1|1,mid+1,r,x,U);
	tr[k]=Push(tr[k<<1|1],tr[k<<1]);
//	cout<<l<<' '<<r<<' '<<tr[k].x<<' '<<tr[k].A1<<' '<<tr[k].A2<<' '<<tr[k].S1<<' '<<tr[k].S2<<endl;
}
Info query(int k,int l,int r,int L,int R)
{
	if(L<=l&&r<=R)return tr[k];
	int mid=(l+r)>>1;
	if(R<=mid)return query(k<<1,l,mid,L,R);
	if(L>mid) return query(k<<1|1,mid+1,r,L,R);
	return Push(query(k<<1|1,mid+1,r,mid+1,R),query(k<<1,l,mid,L,mid));
}
int w[N];
int B[N][30];
LL sum=0;
inline void guess(int x,int &u,int &v)
{
//	cout<<u<<' '<<v<<' '<<B[x][0]<<endl;
	for(int i=0;i<=29;i++)
	if(!B[x][i])
	{
		if(u==-1) u=i;
		else if(v==-1) v=i;
	}
}
void modify(int x)
{
	int p=top[fa[x]];
	while(p)
	{
		Info U=query(1,1,n+1,st[p],ed[p]);
		sum-=U.S2;
		p=top[fa[p]];	
	}
	//w[x]=0;
	update(1,1,n+1,dfn[x],Info(0,1,1,0,0));
	p=top[x];
//	cout<<x<<':'<<dfn[x]<<endl;
	//cout<<query(1,1,n,st[1],ed[1]).S2<<endl;
	while(p)
	{
//	cout<<query(1,1,n,st[1],ed[1]).S2<<endl;
//	cout<<"modify:"<<p<<' '<<w[p]<<' '<<st[p]<<' '<<ed[p]<<' '<<sum<<endl;
		Info U=query(1,1,n+1,st[p],ed[p]);
		sum+=U.S2;
		if(!fa[p])break;
		if(w[p]>=0) B[fa[p]][w[p]]--;
		w[p]=U.A2;
		if(w[p]>=0) B[fa[p]][w[p]]++;
		int u=-1,v=-1;
		guess(fa[p],u,v);
//		cout<<"guess:"<<u<<' '<<v<<endl;
		update(1,1,n+1,dfn[fa[p]],Info(u,v,v,u,u));
		p=top[fa[p]];
	}
//	if(x==3)exit(0);
}
int cr[N];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&cr[i]);
		add(cr[i],i+1);
	}
	for(int i=1;i<=n+1;i++)w[i]=-1;
	dfs(1,0);Exdfs(1,1);
	modify(1);
	for(int i=1;i<=n;i++)
	{
		modify(i+1);
		printf("%lld\n",sum);
	}
	return 0;
} 

相关文章:

  • 网站美工和平面设计师/博客网站注册
  • 域名备案和网站备案区别/seo排名工具给您好的建议
  • 如何开公司做网站/武汉seo结算
  • 网站制作中的更多怎么做/厦门seo优化外包公司
  • 网站搭建空间/培训体系包括四大体系
  • 电子商务网站建设课设学生体会/百度经验实用生活指南
  • Kubernetes:Pod
  • 向云而行 华为云桌面成数字办公首选
  • 35.前端笔记-CSS3-3D转换
  • 【idea插件】EasyCode介绍与使用
  • MCU-51:独立按键控制LED灯的动作
  • GridLayout案例
  • python 多进程进程退不出问题
  • 基于VitePress搭建静态文档系统
  • Docker搭建Mysql主主架构
  • DNS协议分析
  • 从全球顶级数据库大会 SIGMOD 看数据库发展趋势
  • Vue3——vuex的使用——axios网络请求的使用