codeforces 600E. Lomsat gelral

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ccsu_cat/article/details/84036613

E. Lomsat gelral

题意:给一棵树,每个节点有一个编号,求每颗子树最多编号的和。

线段树合并模板题

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
vector<int>G[maxn];
int mx[maxn*20],rt[maxn*20],ls[maxn*20],rs[maxn*20],V[maxn],n,cnt=0;
ll ans[maxn],sum[maxn*20];
void pushup(int o)
{
	mx[o]=max(mx[ls[o]],mx[rs[o]]);
	if(mx[ls[o]]==mx[rs[o]])sum[o]=sum[ls[o]]+sum[rs[o]];
	else
	{
		if(mx[ls[o]]>mx[rs[o]])sum[o]=sum[ls[o]];
		else sum[o]=sum[rs[o]];
	}
}
int merge(int a,int b,int l,int r)
{
	if(!a||!b)return a|b; 
	if(l==r)
	{
		sum[a]=l;
		mx[a]+=mx[b];
		return a;
	}
	int m=(l+r)/2;
	if(ls[a]||ls[b])ls[a]=merge(ls[a],ls[b],l,m);
	if(rs[a]||rs[b])rs[a]=merge(rs[a],rs[b],m+1,r);
	pushup(a);
	return a;
}
void up(int &o,int l,int r,int k)
{
	if(!o)o=++cnt;
	if(l==r)
	{
		mx[o]++;
		sum[o]=l;
		return;
	}
	int m=(l+r)/2;
	if(k<=m)up(ls[o],l,m,k);
	else up(rs[o],m+1,r,k);
	pushup(o);
}
void dfs(int u,int fa)
{
	for(int i=0;i<G[u].size();i++)
	{
		if(G[u][i]==fa)continue;
		dfs(G[u][i],u);
		merge(rt[u],rt[G[u][i]],1,n);
	}
	up(rt[u],1,n,V[u]);
	ans[u]=sum[rt[u]];
}
int main()
{
	int u,v;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&V[i]),rt[i]=++cnt;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(1,0);
	for(int i=1;i<n;i++)printf("%I64d ",ans[i]);
	printf("%I64d\n",ans[n]);
}

看了一些这题关于启发式合并的题解,也需要重链剖分,按照网上大神的代码仿写了一遍,假装自己学懂了启发式合并.....

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
vector<int>G[maxn];
int son[maxn],size[maxn],a[maxn],f[maxn],vis[maxn],cnt[maxn],mx=0;
ll sum=0,ans[maxn];
void dfs(int u,int fa)
{
	f[u]=fa;
	size[u]=1;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i];
		if(v==fa)continue;
		dfs(v,u);
		size[u]+=size[v];
		if(size[v]>size[son[u]])son[u]=v;
	}
}
void cal(int u,int v)
{
	cnt[a[u]]+=v;
	if(cnt[a[u]]==mx)sum+=a[u];
	else if(cnt[a[u]]>mx)sum=a[u],mx=cnt[a[u]];
	for(int i=0;i<G[u].size();i++)
	if(G[u][i]!=f[u]&&!vis[G[u][i]])
	cal(G[u][i],v);
}
void dfs2(int u)
{
	for(int i=0;i<G[u].size();i++)
	if(G[u][i]!=f[u]&&G[u][i]!=son[u])dfs2(G[u][i]);
	if(son[u])dfs2(son[u]),vis[son[u]]=1;
	cal(u,1);
	ans[u]=sum;
	if(son[u])vis[son[u]]=0;
	if(son[f[u]]!=u)cal(u,-1),sum=0,mx=0;
}
int main()
{
	int n,u,v;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(1,0);
	dfs2(1);
	for(int i=1;i<n;i++)printf("%I64d ",ans[i]);
	printf("%I64d\n",ans[n]);
}

猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/84036613