萌新刚学 OI,刚学树剖,貌似又是线段树出锅了(太菜了),求助 qwq
查看原帖
萌新刚学 OI,刚学树剖,貌似又是线段树出锅了(太菜了),求助 qwq
298549
SIXIANG32楼主2020/12/13 16:15
#include<iostream>
#include<vector>
#define MAXN 100000
using namespace std;
int f[MAXN*4+10],S[MAXN*4+10],M[MAXN*4+10],a[MAXN+10],n;
int de[MAXN+10],son[MAXN+10],fa[MAXN+10],siz[MAXN+10];
int ind[MAXN+10],cnt=0,top[MAXN+10],who[MAXN+10];
vector<int>tree[MAXN+10];
int ls(int now){return now<<1;  }
int rs(int now){return now<<1|1;}
void push_up(int now)
{
	S[now]=S[ls(now)]+S[rs(now)];
	M[now]=max(M[ls(now)],M[rs(now)]);
}
void build(int l,int r,int now)
{
	if(l==r)
	{
		S[now]=M[now]=a[who[l]];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls(now));
	build(mid+1,r,rs(now));
	push_up(now);
}
int ask_max(int l,int r,int s,int t,int now) 
{
	int mid=(s+t)>>1,maxn=-725;
	if(l<=s&&r>=t)return M[now];
	if(l<=mid)maxn=max(maxn,ask_max(l,r,s,mid ,ls(now)));
	if(r>mid)maxn=max(maxn,ask_max(l,r,mid+1,r,rs(now)));
	return maxn;
}
int ask_sum(int l,int r,int s,int t,int now) 
{
	int mid=(s+t)>>1,sum=0;
	if(l<=s&&r>=t)return S[now];
	if(l<=mid)sum+=ask_sum(l,r,s,mid ,ls(now));
	if(r>mid)sum+=ask_sum(l,r,mid+1,r,rs(now));
	return sum;
}
void updata(int q,int s,int t,int now,int val)
{
	int mid=(s+t)>>1;
	if(s==t)
	{
		S[now]=M[now]=val;
		return ;
	}
	if(q<=mid)updata(q,s,mid,ls(now),val);
	else updata(q,mid+1,t,rs(now),val);
	push_up(now);
}
//线段树 
void dfs1(int u,int fat)
{
	siz[u]=1,fa[u]=fat,de[u]=de[fat]+1;
	int maxn=0;
	for(int p=0;p<tree[u].size();p++)
	{
		int v=tree[u][p];
		if(v==fat)continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(siz[v]>maxn)
			son[u]=v,maxn=siz[v];
	}
}
void dfs2(int u,int T)
{
	ind[u]=++cnt,who[cnt]=u,top[u]=T;
	if(!son[u])return ;
	dfs2(son[u],T);
	for(int p=0;p<tree[u].size();p++)
	{
		int v=tree[u][p];
		if(v!=fa[u])
			if(v!=son[u])
				dfs2(v,v);
	}
}
//树剖预处理
int QMAX(int u,int v)
{
	int maxn=-0x3f3f3f3f;
	while(top[u]!=top[v])
	{
		if(de[top[u]]<de[top[v]])swap(u,v);
		maxn=max(maxn,ask_max(ind[top[u]],ind[u],1,n,1));
		cout<<maxn<<endl;
		u=fa[top[u]];
	}
	if(de[u]>de[v])swap(u,v);
	maxn=max(maxn,ask_max(ind[u],ind[v],1,n,1));
	return maxn;
}
int QSUM(int u,int v)
{
	int sum=0;
	while(top[u]!=top[v])
	{
		if(de[top[u]]<de[top[v]])swap(u,v);
		sum+=ask_sum(ind[top[u]],ind[u],1,n,1);
		cout<<sum<<endl;
		u=fa[top[u]];
	}
	if(de[u]>de[v])swap(u,v);
	sum+=ask_sum(ind[u],ind[v],1,n,1);
	return sum;
}
void CHANGE(int u,int val)
{
	updata(who[u],1,n,1,val);
}
//树剖 
void link(int x,int y)
{
	tree[x].push_back(y);
	tree[y].push_back(x);
} 
signed main()
{
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	cin>>n;
	for(int p=1,x,y;p<n;p++)
		cin>>x>>y,link(x,y);
	for(int p=1;p<=n;p++)
		cin>>a[p];
	de[1]=1,fa[1]=-1;
	dfs1(1,-1),dfs2(1,1);
	build(1,n,1);
	int q;
	cin>>q;
	string str;
	while(q--)
	{
		int x,y;
		cin>>str>>x>>y;
		if(str=="CHANGE")CHANGE(x,y);
		else if(str=="QMAX")cout<<QMAX(x,y)<<endl;
		else if(str=="QSUM")cout<<QSUM(x,y)<<endl;
	}
}
 

有些输出是调试,别在意。
对照题解看了很多遍,不明白线段树哪里错了(估计是眼瞎原因),求助/kk

2020/12/13 16:15
加载中...