求助关于线段树
查看原帖
求助关于线段树
375953
Lgx_Q楼主2022/12/24 11:03

类似于扫描线,在 DFS 序上覆盖线段

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=5e5+10;
ll n,m,u,v,head[maxn],tot,sum[maxn],cnt[maxn],wsum[maxn],L[maxn],R[maxn],T,op,x,y,br[maxn];
struct edge
{
	ll v,nxt;
}e[maxn];
void insert(ll u,ll v)
{
	e[++tot]=(edge){v,head[u]};
	head[u]=tot;
}
void up(ll p)
{
	sum[p]=sum[p<<1]+sum[p<<1|1];
	if(cnt[p]>0) wsum[p]=sum[p];
	else wsum[p]=wsum[p<<1]+wsum[p<<1|1];
}
void modify(ll p,ll l,ll r,ll x,ll v)
{
	if(l==r)
	{
		sum[p]=v;
		if(cnt[p]) wsum[p]=v;
		else wsum[p]=0;
		return;
	}
	ll mid=l+r>>1;
	if(x<=mid) modify(p<<1,l,mid,x,v);
	else modify(p<<1|1,mid+1,r,x,v);
	up(p);
}
void add(ll p,ll l,ll r,ll ql,ll qr,ll v)
{
	if(ql<=l&&r<=qr)
	{
		cnt[p]+=v;
		if(cnt[p]) wsum[p]=sum[p];
		else wsum[p]=wsum[p<<1]+wsum[p<<1|1];
		return;
	}
	if(r<ql||qr<l) return;
	ll mid=l+r>>1;
	add(p<<1,l,mid,ql,qr,v);
	add(p<<1|1,mid+1,r,ql,qr,v);
	up(p);
}
void dfs(ll u,ll fa)
{
	L[u]=++T;
	for(ll i=head[u];i;i=e[i].nxt)
	{
		ll v=e[i].v;
		if(v!=fa) dfs(v,u);
	}
	R[u]=T;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	for(ll i=1;i<n;i++)
	{
		scanf("%lld%lld",&u,&v);
		insert(u,v);
		insert(v,u);
	}
	dfs(1,1);
	for(ll i=1;i<=n;i++)
	{
		scanf("%lld",&x);
		modify(1,1,n,L[i],x);
	}
	while(m--)
	{
		scanf("%lld%lld",&op,&x);
		if(op==1)
		{
			scanf("%lld",&y);
			modify(1,1,n,L[x],y);
		}
		else
		{
			add(1,1,n,L[x],R[x],br[x]?-1:1);
			br[x]^=1;
		}
		printf("%lld\n",sum[1]-wsum[1]);
	}
	return 0;
}
2022/12/24 11:03
加载中...