CodeForces - 343D Water Tree 树链剖分+线段树+dfs序

题目链接:点击查看

题意:n个节点,原先都是空的,1,x 让x的所有孩子包括x都变成满的,2,x 让x的所有父辈加上x都变成空的,3,x 询问x这个节点是满的还是空的,满的输出1,空的输出0

题解:对应1操作,我们dfs序一下即可,对于2操作我们用树链剖分来解决,然后直接查询即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
struct node{
	int l,r;
	int val,laz;
}tree[N<<2];
struct edge{
	int to,nex;
}e[N*2];
int n,m;
int val[N];
int head[N],len;
int in[N],out[N],p[N],cnt;
int son[N],s_num[N],fath[N],root[N];
void init()
{
	len=cnt=0;
	for(int i=1;i<=n;i++)
		head[i]=-1;
}
void addedge(int x,int y)
{
	e[len].to=y;
	e[len].nex=head[x];
	head[x]=len++;
}
void dfs1(int u,int fa)
{
	s_num[u]=1;
	int to,maxx=-1,id=-1;
	for(int i=head[u];~i;i=e[i].nex)
	{
		to=e[i].to;
		if(to==fa)continue;
		dfs1(to,u);
		s_num[u]+=s_num[to];
		if(s_num[to]>maxx)
		{
			maxx=s_num[to];
			id=to;
		}
	}
	son[u]=id;
}
void dfs2(int u,int fa,int rt)
{
	in[u]=++cnt;
	p[cnt]=u;
	fath[u]=fa;
	root[u]=rt;
	if(son[u]!=-1)
	{
		dfs2(son[u],u,rt);
	}
	int to;
	for(int i=head[u];~i;i=e[i].nex)
	{
		to=e[i].to;
		if(to==fa||to==son[u])continue;
		dfs2(to,u,to);
	}
	out[u]=cnt;
}

void pushdown(int cur)
{
	if(tree[cur].laz!=-1)
	{
		tree[cur<<1].laz=tree[cur].laz;
		tree[cur<<1|1].laz=tree[cur].laz;
		tree[cur<<1].val=tree[cur].laz;
		tree[cur<<1|1].val=tree[cur].laz;
		tree[cur].laz=-1;
	}
}
void build(int l,int r,int cur)
{
	tree[cur].l=l;
	tree[cur].r=r;
	tree[cur].val=0;
	tree[cur].laz=-1;
	if(l==r)
	{
		return;
	}
	int mid=(r+l)>>1;
	build(l,mid,cur<<1);
	build(mid+1,r,cur<<1|1);
}
void update(int pl,int pr,int cur,int val)
{
	if(pl<=tree[cur].l&&tree[cur].r<=pr)
	{
		tree[cur].val=val;
		tree[cur].laz=val;
		return;
	}
	pushdown(cur);
	if(pl<=tree[cur<<1].r) update(pl,pr,cur<<1,val);
	if(pr>=tree[cur<<1|1].l)update(pl,pr,cur<<1|1,val);
}
int query(int pos,int cur)
{
	if(tree[cur].l==tree[cur].r)
	{
		return tree[cur].val;
	}
	pushdown(cur);
	if(pos<=tree[cur<<1].r) return query(pos,cur<<1);
	else return query(pos,cur<<1|1);
}
void solve(int x)
{
	int f1=root[x];
	while(f1!=1)
	{
//		cout<<in[f1]<<" "<<in[x]<<endl;
		update(in[f1],in[x],1,0);
		x=fath[x];
		f1=root[x];
	}
//	cout<<in[x]<<endl;
	update(1,in[x],1,0);
}
int main()
{
	scanf("%d",&n);
	init();
	int x,y;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		addedge(x,y);
		addedge(y,x);
	}
	dfs1(1,0);
	dfs2(1,0,1);
	build(1,n,1);
	scanf("%d",&m);	
	int op;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&op,&x);
		if(op==1)
		{
			update(in[x],out[x],1,1);
		}
		else if(op==2)
		{
			solve(x);
		}
		else if(op==3)
		{
			printf("%d\n",query(in[x],1));
		}
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/89320500