树链剖分 WA on #1 求调
查看原帖
树链剖分 WA on #1 求调
779970
lunjiahao楼主2024/3/27 19:17
#include<bits/stdc++.h>
#define ll long long
#define ls u<<1
#define rs u<<1|1
using namespace std;
const int N=1e5+5;
int n,q,a[N],b[N],root;
ll t[N<<2],tag[N<<2];
int cnt,fa[N],dep[N],siz[N],hs[N],w[N],top[N];
vector<int> g[N];
void dfs1(int u,int fath)
{
	fa[u]=fath;
	dep[u]=dep[fath]+1;
	siz[u]=1;
	hs[u]=-1;
	for(auto v:g[u])
	{
		if(v==fath) continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(hs[u]==-1||siz[v]>siz[hs[u]]) hs[u]=v;
	}
}
void dfs2(int u,int t)
{
	top[u]=t;
	w[u]=++cnt;
	b[cnt]=a[u];
	if(hs[u]!=-1) dfs2(hs[u],t);
	for(auto v:g[u])
		if(v!=hs[u]&&fa[u]!=v)
			dfs2(v,v);
}
void push_up(int u)
{
	t[u]=t[ls]+t[rs];
}
void build(int u,int l,int r)
{
	if(l==r)
	{
		t[u]=b[l];
		return;
	}
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	push_up(u);
}
void push_down(int u,int l,int r)
{
	if(!tag[u]) return;
	tag[ls]+=tag[u];
	tag[rs]+=tag[u];
	int mid=(l+r)>>1;
	t[ls]+=tag[u]*(mid-l+1);
	t[rs]+=tag[u]*(r-mid);
	tag[u]=0;
}
void update(int u,int l,int r,int x,int y,int k)
{
	if(y<l||r<x) return;
	if(x<=l&&r<=y)
	{
		tag[u]+=k;
		t[u]+=k*(r-l+1);
		return;
	}
	push_down(u,l,r);
	int mid=(l+r)>>1;
	if(x<=mid) update(ls,l,mid,x,y,k);
	if(y>mid) update(rs,mid+1,r,x,y,k);
	push_up(u);
}
ll query(int u,int l,int r,int x,int y)
{
	if(y<l||r<x) return 0;
	if(x<=l&&r<=y) return t[u];
	push_down(u,l,r);
	int mid=(l+r)>>1;
	ll res=0;
	if(x<=mid) res+=query(ls,l,mid,x,y);
	if(y>mid) res+=query(rs,mid+1,r,x,y);
	return res;
}
int lca(int u,int v)
{
	while(top[u]^top[v])
	{
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		u=fa[top[u]];
	}
	if(dep[u]<dep[v]) swap(u,v);
	return v;
}
int LCA(int u,int v)
{
	if(dep[u]>dep[v]) swap(u,v);
	int u_rt=lca(u,root),v_rt=lca(v,root),u_v=lca(u,v);
	if(u_v==u)
	{
		if(u_rt==u)
		{
			if(v_rt==v) return v;
			return v_rt;
		}
		return u;
	}
	if(u_rt==u) return u;
	if(v_rt==v) return v;
	if((u_rt==root&&u_v==v_rt)||(v_rt==root&&u_v==u_rt)) return root;
	if(u_rt==v_rt) return u_v;
	if(u_rt^v_rt) return u_rt;
	return v_rt;
}
int find(int u,int v)
{
	while(top[u]^top[v])
	{
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		if(fa[top[u]]==v) return top[u];
		u=fa[top[u]];
	}
	if(dep[u]<dep[v]) swap(u,v);
	return hs[v];
}
void modify(int u,ll k)
{
	if(u==root)
	{
		update(1,1,n,1,n,k);
		return;
	}
	if(w[root]>=w[u]&&w[root]<=w[u]+siz[u]-1)
	{
		int v=find(u,root);
		update(1,1,n,1,n,k);
		update(1,1,n,w[v],w[v]+siz[v]-1,-k);
	}
	else update(1,1,n,w[u],w[u]+siz[u]-1,k);
}
ll query(int u)
{
	if(u==root) return query(1,1,n,1,n);
	if(w[root]>=w[u]&&w[root]<=w[u]+siz[u]-1)
	{
		int v=find(u,root);
		return query(1,1,n,1,n)-query(1,1,n,w[v],w[v]+siz[v]-1);
	}
	else return query(1,1,n,w[u],w[u]+siz[u]-1);
}
signed main()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",a+i);
	for(int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	root=1;
	dfs1(1,0);
	dfs2(1,1);
	build(1,1,n);
	while(q--)
	{
		int opt,x,y;
		ll k;
		scanf("%d",&opt);
		if(opt==1) scanf("%d",&root);
		if(opt==2) scanf("%d%d%lld",&x,&y,&k),modify(LCA(x,y),k);
		if(opt==3) scanf("%d",&x),printf("%lld\n",query(x));
	}
	return 0;
}
2024/3/27 19:17
加载中...