树链剖分求助!
查看原帖
树链剖分求助!
186138
ywsh27楼主2022/7/22 11:03
#include<bits/stdc++.h>
using namespace std;
#define int long long 
struct Node{
	int nex,to;
}edge[200001];
int heads[200001],num;
inline void add(int u,int v)
{
	++num;
	edge[num].nex=heads[u];
	edge[num].to=v;
	heads[u]=num;
}
int n,m;
int fa[200001],deep[200001],totree[200001],son[200001];
int dfs1(int now,int f)
{
	fa[now]=f;
	deep[now]=deep[f]+1;
	totree[now]=1;
	int maxson=-1;
	for(int i=heads[now];i!=0;i=edge[i].nex)
	{
		if(edge[i].to==f)continue;
		totree[now]+=dfs1(edge[i].to,now);
		if(totree[edge[i].to]>maxson)maxson=totree[edge[i].to],son[now]=edge[i].to;
	}
	return totree[now];
}
int top[200001],idx[200001],cnt,a[200001],b[200001];
void dfs2(int now,int topf)
{
	idx[now]=++cnt;
	top[now]=topf;
	a[cnt]=b[now];
	if(!son[now])return ;
	dfs2(son[now],topf);
	for(int i=heads[now];i!=0;i=edge[i].nex)
		if(!idx[edge[i].to])dfs2(edge[i].to,edge[i].to);
}
int tree[400001],tag[400001],tree_max[400001];
void build(int node,int start,int end)
{
	if(start==end){tree[node]=a[start];tree_max[node]=a[start];return ;}
	int mid=(start+end)/2,left_node=2*node,right_node=2*node+1;
	build(left_node,start,mid);build(right_node,mid+1,end);
	tree[node]=tree[left_node]+tree[right_node];
	tree_max[node]=max(tree[left_node],tree[right_node]);
}
void update(int newl,int newr,int l,int r,int node,int val)
{
	if(newl<=l&&r<=newr){tree[node]=val;tree_max[node]=val;return ;}
	int mid=(l+r)/2,left_node=2*node,right_node=2*node+1;
	if(newl<=mid)update(newl,newr,l,mid,left_node,val);
	if(newr>mid) update(newl,newr,mid+1,r,right_node,val);
	tree[node]=tree[left_node]+tree[right_node];
	tree_max[node]=max(tree[left_node],tree[right_node]);
}
int query(int query_left,int query_right,int l,int r,int node)
{
	if(query_left<=l&&r<=query_right)return tree[node];
	int mid=(l+r)/2,left_node=2*node,right_node=2*node+1,res=0;
	if(query_left<=mid)res+=query(query_left,query_right,l,mid,left_node);
	if(query_right>mid)res+=query(query_left,query_right,mid+1,r,right_node);
	return res;
}
int query_max(int query_left,int query_right,int l,int r,int node)
{
	if(query_left<=l&&r<=query_right)return tree_max[node];
	int mid=(l+r)/2,left_node=2*node,right_node=2*node+1,res1,res2;
	if(query_left<=mid)res1=query_max(query_left,query_right,l,mid,left_node);
	if(query_right>mid)res2=query_max(query_left,query_right,mid+1,r,right_node);
	return max(res1,res2);
}
void TreeAdd(int x,int y,int val)
{
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		update(idx[top[x]],idx[x],1,n,1,val);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	update(idx[x],idx[y],1,n,1,val);
}
void TreeSum(int x,int y)
{
	int res=0;
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		res+=query(idx[top[x]],idx[x],1,n,1);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	res+=query(idx[x],idx[y],1,n,1);
	cout<<res<<endl;
}
void TreeMax(int x,int y)
{
	int res=0;
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		res=max(res,query_max(idx[top[x]],idx[x],1,n,1));
		x=fa[top[x]];
	}
	if(deep[x]>deep[y])swap(x,y);
	res=max(res,query_max(idx[x],idx[y],1,n,1));
	cout<<res<<endl;
}
signed main()
{
	int bol,x,y,z;
	scanf("%lld",&n);
	for(int i=1;i<n;++i)scanf("%lld%lld",&x,&y),add(x,y),add(y,x);
	for(int i=1;i<=n;++i)scanf("%lld",&b[i]);
	dfs1(1,0);
	dfs2(1,1);
	build(1,1,n);
	scanf("%lld",&m);
	while(m--)
	{
		char ch[12];
		cin>>ch;
		if(ch[1]=='H'){scanf("%lld%lld",&x,&y);TreeAdd(x,x,y);continue;}
		if(ch[1]=='M'){scanf("%lld%lld",&x,&y);TreeMax(x,y);continue;}
		if(ch[1]=='S'){scanf("%lld%lld",&x,&y);TreeSum(x,y);continue;}
	}
	return 0;
}
2022/7/22 11:03
加载中...