【树剖】CF1017G The Tree

题目

自己看去

题解

通过脑子和观察发现 我没有脑子
染一个点就在此加1,查询时判断从此节点向上的连续区间最大值是否大于等于0,记得赋初值(num,maxx都要赋成-1)
清零就让该子树每个点查询值为-1,操作来说就是子树点权都变成-1,该节点赋为 负 的 ( 查 询 值 + 1 ) 负的(查询值+1) +1即可
树剖记得初始化赋为-1

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,M=N,INF=1e9;
int n,q;
int head[N],nex[M],to[M],tot;
void creat(int u,int v)
{
	tot++;nex[tot]=head[u];to[tot]=v;head[u]=tot;
}
int dep[N],son[N],fa[N],tp[N],sz[N];
int dfn[N],cnt;
void dfs1(int u,int f)
{
	dep[u]=dep[f]+1,fa[u]=f;sz[u]=1;
	for(int i=head[u];i;i=nex[i])
	{
		int v=to[i];if(v==f)continue;
		dfs1(v,u);sz[u]+=sz[v];
		if(sz[son[u]]<sz[v])son[u]=v;
	}
}
void dfs2(int u,int f)
{
	tp[u]=f;dfn[u]=++cnt;
	if(son[u])dfs2(son[u],f);
	for(int i=head[u];i;i=nex[i])
	{
		int v=to[i];if(dfn[v])continue;
		dfs2(v,v);
	}
}
//-
#define ls lson[x]
#define rs rson[x]
struct qwq{int num,maxx;qwq(int x=0,int y=0){num=x,maxx=y;}};
qwq mer(qwq a,qwq b){return qwq(a.num+b.num,max(b.maxx,b.num+a.maxx));}
int key;
int lson[N*4],rson[N*4];
bool tag[N*4]; qwq t[N*4];
void updata(int x)
{
	if(ls&&rs){t[x]=mer(t[ls],t[rs]);return ;}
	if(ls)t[x]=t[ls];if(rs)t[x]=t[rs];
}
void pushdown(int x,int l,int r)
{
	if(tag[x])
	{
		int mid=(l+r)>>1;
		if(ls)tag[ls]=1,t[ls].num=-(mid-l+1),t[ls].maxx=-1;
		if(rs)tag[rs]=1,t[rs].num=-(r-mid)  ,t[rs].maxx=-1;
		tag[x]=0;		
	}
}
void build(int x,int l,int r)
{
	if(l==r){t[x].num=-1;t[x].maxx=-1;return ;}
	int mid=(l+r)>>1;
	build(ls=x<<1,l,mid);
	build(rs=x<<1|1,mid+1,r);
	updata(x);
//	printf("[%d,%d]%d=%d\n",l,r,x,t[x].maxx);
}
void add(int x,int l,int r,int goal)
{
	pushdown(x,l,r);
	if(l==r){t[x].num+=key;t[x].maxx+=key;return ;}
	int mid=(l+r)>>1;
	if(goal<=mid)add(ls,l,mid,goal);
	else		 add(rs,mid+1,r,goal);
	updata(x);
}
void cover(int x,int l,int r,int ll,int rr)
{
	pushdown(x,l,r);
	if(ll<=l&&r<=rr){t[x].num=-(r-l+1);t[x].maxx=-1;tag[x]=1;return ;}
	int mid=(l+r)>>1;
	if(ll<=mid)cover(ls,l,mid,ll,rr);
	if(mid<rr) cover(rs,mid+1,r,ll,rr);
	updata(x);
}
qwq qur(int x,int l,int r,int ll,int rr)
{
	pushdown(x,l,r);
	if(ll<=l&&r<=rr){return t[x];}
	int mid=(l+r)>>1;
	if(rr<=mid)		return qur(ls,l,mid,ll,rr);
	else if(mid<ll) return qur(rs,mid+1,r,ll,rr);
	else			return mer(qur(ls,l,mid,ll,rr),qur(rs,mid+1,r,ll,rr));
	updata(x);
}
//--
int Q_qur(int x)
{
	qwq tmp=qwq(0,-INF);
	while(x)
	{
		//tmp=mer(qur(1,1,n,dfn[tp[x]],dfn[x]),tmp);
		qwq st=qur(1,1,n,dfn[tp[x]],dfn[x]);
//		printf("{%d,%d}[%d,%d]",tp[x],x,st.num,st.maxx);
		tmp=mer(st,tmp);
		x=fa[tp[x]];
	}
	return tmp.maxx;
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int fw,i=2;i<=n;i++)scanf("%d",&fw),creat(fw,i);
	dfs1(1,0);dfs2(1,1);
	build(1,1,n);
//	for(int i=1;i<=n;i++)printf("[%d]%d,%d ",i,dfn[i],tp[i]);
	while(q--)
	{
//		for(int i=1;i<=n;i++)
//		printf("%d ",Q_qur(i));printf("\n");
		int op,x;
		scanf("%d%d",&op,&x);
		if(op==1)     key=1,add(1,1,n,dfn[x]);
		else if(op==2)
		{
			key=-1;cover(1,1,n,dfn[x],dfn[x]+sz[x]-1);
			int fw=Q_qur(x);
			if(fw>=0)key=-fw-1,add(1,1,n,dfn[x]);
		}
		else
		{
			if(Q_qur(x)>=0)printf("black\n");
			else		   printf("white\n");
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值