「2019-8-13提高模拟赛」树 (tree)

传送门

Description

你有一个 \(n\)个点的树,第 \(i\)个点的父亲是\(p_i\)。每个点有一个权值 \(t_i\) 和一个颜色黑或者白。所有点一开始都是白色。

你要进行 \(m\)次操作,每次给一个点换颜色(从白变成黑,从黑变成白),在每次操作结束时,问有多少个白点 \(i\) 的子树内黑点的个数大于 \(t_i\)

Solution 

相当于每次修改一条链的\(t_i\),让它们\(+1/-1\)

树链剖分后分块处理

复杂度\(O(n\sqrt n \log n)\)

Code 

/*树剖+分块*/
#include<bits/stdc++.h>
#define ll long long
#define dbg1(x) cerr<<#x<<"="<<(x)<<" "
#define dbg2(x) cerr<<#x<<"="<<(x)<<"\n"
#define dbg3(x) cerr<<#x<<"\n"
using namespace std;
#define reg register
#define db double
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
const int MN=1e5+5,A=1e5;
int fa[MN],n,m;
vector<int> G[MN];
int siz[MN],mx[MN];
void dfs1(int x)
{
	reg int i;siz[x]=1;
	for(i=G[x].size()-1;~i;--i)
	dfs1(G[x][i]),siz[x]+=siz[G[x][i]],siz[G[x][i]]>siz[mx[x]]?mx[x]=G[x][i]:0;
}
int dind,id[MN],dfn[MN],top[MN];
void dfs2(int x,int tp)
{
	id[dfn[x]=++dind]=x;top[x]=tp;if(mx[x])dfs2(mx[x],tp);reg int i;
	for(i=G[x].size()-1;~i;--i)if(G[x][i]^mx[x])dfs2(G[x][i],G[x][i]);
}
int BL,cnt[500][MN<<1],t[MN],tag[500],T,bel[MN],ans;
bool col[MN];
void init()
{
	reg int i,l,r;
	for(i=1;i<=n;++i) t[dfn[i]]=read();
	BL=(int)ceil((db)sqrt(n));
	for(T=1,l=1,r=BL;l<=n;++T,l=r+1,r=min(r+BL,n))
		for(i=l;i<=r;++i)bel[i]=T,++cnt[T][t[i]+A];
}
void swi(int x)
{
	if(col[x]){++cnt[bel[x]][t[x]+A];if(t[x]<tag[bel[x]])++ans;}
	else{--cnt[bel[x]][t[x]+A];if(t[x]<tag[bel[x]])--ans;}col[x]^=1;
}
void rough(int L,int R,int v)
{
	int x=bel[L],l=BL*x-BL+1,r=min(n,BL*x),i;
	for(i=l;i<=r;++i)if(!col[i])--cnt[x][t[i]+A],ans-=(t[i]<tag[x]);
	for(i=l;i<=r;++i)t[i]-=tag[x];tag[x]=0;
	for(i=L;i<=R;++i)t[i]-=v;
	for(i=l;i<=r;++i)if(!col[i])++cnt[x][t[i]+A],ans+=(t[i]<tag[x]);
}
void sol(int L,int R,int v)
{
	int xl=bel[L],xr=bel[R];
	if(xl==xr)rough(L,R,v);
	else
	{
		rough(L,xl*BL,v);rough(xr*BL-BL+1,R,v);
		for(++xl;xl<xr;++xl)ans+=v*cnt[xl][tag[xl]-(v<0)+A],tag[xl]+=v;
	}
}
void Upd(int x,int v){swi(dfn[x]);while(x)sol(dfn[top[x]],dfn[x],v),x=fa[top[x]];printf("%d ",ans);}
int main()
{
#ifndef LOCAL
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
#endif
	n=read(),m=read();reg int i,q;
	for(i=2;i<=n;++i)G[fa[i]=read()].push_back(i);
	dfs1(1);dfs2(1,1);init();
	while(m--) q=read(),Upd(abs(q),q/abs(q));
	return 0;
}


Blog来自PaperCloud,未经允许,请勿转载,TKS!

posted @ 2019-08-13 17:26  PaperCloud  阅读(191)  评论(0编辑  收藏  举报