首页 > 其他分享 >[BJOI2017] 树的难题

[BJOI2017] 树的难题

时间:2024-07-17 21:07:11浏览次数:15  
标签:难题 颜色 int ll BJOI2017 return && const

这道题目卡常卡了两个半小时仍然没有卡过。。。等进队了让队友帮忙卡一下吧

主要想一下思路

最主要的就是在计算路径长度的时候,假设当前递归到了点\(i\),那么从点\(i\)出发的两条路径合并在一起,如果第一条边的颜色相同的话就会重复计算,为了解决这个问题,我们只用对每个点进行排序,将相同颜色的点放在一起,处理相同颜色的点内部,以及不同颜色的点之间的路径就好了,代码如下

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
const ll INF=1e12;
int n,m,L,R;
ll c[N],maxdis[N];
ll Max[N<<2][2];
int siz[N],maxx[N];
struct node
{
	int num,color;
}temp;
vector<node> G[N];
int tag[2][N],New[N],TAG[2],NEW;
bool vis[N],ins[N],tf[2][N];
int sum,rt;
ll ans;
ll dist[N];
int len[N];
inline ll mymax(ll a,ll b)
{
	return a>b?a:b;
}
void calcsiz(int x,int fa) 
{
  	siz[x]=1;
  	maxx[x]=0;
  	for(register int j=0;j<G[x].size();j++)
    if(G[x][j].num!=fa&&!vis[G[x][j].num]) 
	{
      	calcsiz(G[x][j].num,x);
      	maxx[x]=mymax(maxx[x],siz[G[x][j].num]);
      	siz[x]+=siz[G[x][j].num];
    }
  	maxx[x]=mymax(maxx[x],sum-siz[x]);
  	if(maxx[x]<maxx[rt]) rt=x;
}
ll ask(int p,int l,int r,bool op,int x,int y)
{
	if(l>y||r<x) return -INF;
	if(l>=x&&r<=y) return Max[p][op];
	int mid=l+r>>1;
	return mymax(ask(p<<1,l,mid,op,x,y),ask(p<<1|1,mid+1,r,op,x,y));
}
void calcdist(int x,int fa,int col) 
{
	maxdis[len[x]]=mymax(maxdis[len[x]],dist[x]);
	//这里卡常,然而却没有什么用 
	if(!ins[len[x]])
	{
		New[NEW++]=len[x];
		ins[len[x]]=1;
		if(!tf[0][len[x]])
		{
			tf[0][len[x]]=1;
			tag[0][TAG[0]++]=len[x];
		}
	}
	if(len[x]<=R)
	ans=mymax(ans,dist[x]+ask(1,1,n+1,0,mymax(L-len[x],0)+1,R-len[x]+1));
  	for(register int j=0;j<G[x].size();j++)
    if(G[x][j].num!=fa&&!vis[G[x][j].num])
    {
    	len[G[x][j].num]=len[x]+1;
    	if(col!=G[x][j].color) dist[G[x][j].num]=dist[x]+c[G[x][j].color];
    	else dist[G[x][j].num]=dist[x];
		calcdist(G[x][j].num,x,G[x][j].color);
	} 
}
void modify(int p,int l,int r,bool op,int x,ll d)
{
	if(l>x||r<x) return;
	if(l==r)
	{
		if(d!=-INF) Max[p][op]=mymax(d,Max[p][op]);
		else Max[p][op]=d;
        //这里千万注意,如果是还原的话可以直接赋值,但是如果是更新的话一定要先比较
		return;
	}
	int mid=l+r>>1;
	modify(p<<1,l,mid,op,x,d);
	modify(p<<1|1,mid+1,r,op,x,d);
	Max[p][op]=mymax(Max[p<<1][op],Max[p<<1|1][op]);
}
bool cmp(node i,node j)
{
	if(vis[i.num]==vis[j.num]) return i.color<j.color;
	else return vis[i.num]<vis[j.num];
}
void dp(int x,int fa,int col)
{
	maxdis[len[x]]=mymax(maxdis[len[x]],dist[x]);
	if(!ins[len[x]])
	{
		New[NEW++]=len[x];
		ins[len[x]]=1;
	}
	if(len[x]<=R)
	ans=mymax(ans,dist[x]+ask(1,1,n+1,1,mymax(L-len[x],0)+1,R-len[x]+1)-c[col]);
  	for(register int j=0;j<G[x].size();j++)
    if(G[x][j].num!=fa&&!vis[G[x][j].num])
    dp(G[x][j].num,x,col);
}
void dfs(int x,int fa)
{
	tf[0][0]=1;
	tag[0][TAG[0]++]=0;
  	modify(1,1,n+1,0,1,0); 
  	vis[x]=1;
  	sort(G[x].begin(),G[x].end(),cmp);
  	//将颜色相同的放在一起 
  	for(register int j=0;j<G[x].size();)
    if(G[x][j].num!=fa&&!vis[G[x][j].num]) 
	{
      	int k=j;
      	while(j<G[x].size()&&!vis[G[x][j].num]&&G[x][k].color==G[x][j].color)
      	{
      		len[G[x][j].num]=1,dist[G[x][j].num]=c[G[x][j].color];
      		calcdist(G[x][j].num,x,G[x][j].color);
      		j++;
		}//找出同一颜色的儿子 
		for(register int o=0;o<NEW;o++) modify(1,1,n+1,0,New[o]+1,maxdis[New[o]]);
		for(register int o=0;o<NEW;o++)
		maxdis[New[o]]=-INF;
		for(register int o=0;o<NEW;o++)
		ins[New[o]]=0;
		NEW=0;
		for(register int o=k;o<j;o++)//处理同一颜色的点 
		{
			dp(G[x][o].num,x,G[x][o].color);
			for(register int w=0;w<NEW;w++) modify(1,1,n+1,1,New[w]+1,maxdis[New[w]]);
			for(register int w=0;w<NEW;w++)
			if(!tf[1][New[w]])
			{
				tf[1][New[w]]=1;
				tag[1][TAG[1]++]=New[w];
			}
			for(register int w=0;w<NEW;w++)
			maxdis[New[w]]=-INF;
			for(register int w=0;w<NEW;w++)
			ins[New[w]]=0;
			NEW=0;
		}
		for(register int o=0;o<TAG[1];o++)
		modify(1,1,n+1,1,tag[1][o]+1,-INF);
		for(register int o=0;o<TAG[1];o++)
		tf[1][tag[1][o]]=0;
		TAG[1]=0;
    }
    else break;
    for(register int j=0;j<TAG[0];j++)
	modify(1,1,n+1,0,tag[0][j]+1,-INF);
	for(register int j=0;j<TAG[0];j++)
	tf[0][tag[0][j]]=0;
	TAG[0]=0;
  	for(register int j=0;j<G[x].size();j++)
    if(G[x][j].num!=fa&&!vis[G[x][j].num]) 
	{
      sum=siz[G[x][j].num];
      rt=0;
      maxx[rt]=n+1;
      calcsiz(G[x][j].num,x);
      calcsiz(rt,0);
      dfs(rt,x);
    }
}
void build(int p,int l,int r)
{
	if(l==r)
	{
		for(register int i=0;i<=1;i++) 
		Max[p][i]=-INF;
		return;
	}
	int mid=l+r>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	for(register int i=0;i<=1;i++) 
	Max[p][i]=-INF;
}
int read()
{
    int x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-48;s=getchar();}
    return x*f;
}
int main() 
{
  	n=read(),m=read(),L=read(),R=read();
  	for(register int i=1;i<=n;i++) maxdis[i]=-INF;
  	build(1,1,n+1);
  	//注意,线段树的下标表示长度,而且整体加了一 
  	//0表示不同颜色的线段树,1表示相同颜色的线段树 
  	for(register int i=1;i<=m;i++)
  	c[i]=read();
  	for(register int i=1,a,b,c;i<n;i++)
    {
    	a=read(),b=read(),c=read();
    	temp.num=b,temp.color=c;
		G[a].push_back(temp);
		temp.num=a;
		G[b].push_back(temp);
	}
  	rt=0;
  	maxx[rt]=n+1;
  	sum=n;
  	calcsiz(1,0);
  	calcsiz(rt,0);
  	ans=-INF;
  	dfs(rt,0);
  	printf("%lld",ans);
  	return 0;
}

标签:难题,颜色,int,ll,BJOI2017,return,&&,const
From: https://www.cnblogs.com/dingxingdi/p/18308299

相关文章

  • 《QQ三国》bugreportnew.dll 加载失败:游戏启动难题的深度解析与修复
    遇到《QQ三国》游戏加载bugreportnew.dll失败的问题,通常意味着游戏在启动或运行时未能成功加载或初始化bugreportnew.dll这个动态链接库(DynamicLinkLibrary)文件。bugreportnew.dll文件可能是游戏内置错误报告系统的一部分,用于在游戏崩溃或遇到问题时收集错误信息并生成报告。......
  • 游戏启动难题破解:《天涯明月刀》gbspy64.dll 报错问题的修复手册
    遇到《天涯明月刀》(简称“天刀”)游戏报错模块gbspy64.dll的问题,意味着游戏在启动或运行时未能成功加载或初始化这个动态链接库(DynamicLinkLibrary)文件。gbspy64.dll文件可能与游戏的反作弊系统、性能监控或某些游戏内功能紧密相关。以下是解决gbspy64.dll问题的步骤:1.重新......
  • 免抠图神器:轻松解决素材难题,释放无限创意
    有小伙伴抱怨,做PPT找素材是一件让人头疼不已的事情。花费大量时间搜索到的图片,不是分辨率低,就是模糊不清,放到PPT里显得特别不专业。但别担心,今天要给大家介绍一款令人惊喜的免抠图神器——千鹿设计助手。千鹿设计助手为用户提供了丰富的免抠图素材。无论您是需要人物、风......
  • 面试中如果被问到项目遇到的难题如何解决
    1大数据量问题:一案例:在一个电子商务平台中,随着用户和交易量的增长,数据库中的订单数据量迅速增加,导致查询和分析变得非常缓慢。二解决方案:1数据库分片:具体实现可以使用数据库中间件如ShardingSphere,它支持多种分片策略,如哈希分片、范围分片等。例如,可以根据......
  • 巧用 DirectX 化解游戏频繁卡顿难题
    在游戏的精彩世界中,频繁的卡顿无疑是令人扫兴的体验。但别担心,通过合理利用DirectX(DX)的相关功能和设置,我们往往能够有效地解决这一问题。首先,我们需要确认当前系统中安装的DirectX版本是否是最新的。按下“Win+R”键,输入“dxdiag”并回车,在弹出的DirectX诊断工具中可......
  • 一劳永逸解决路径难题:PyCharm中Python解释器路径错误的终极指南
    一劳永逸解决路径难题:PyCharm中Python解释器路径错误的终极指南引言PyCharm作为Python开发者的强大IDE,提供了许多便利的功能来简化开发流程。然而,在使用PyCharm时,可能会遇到Python解释器路径错误的问题,这通常会导致项目无法正常运行或调试。本文将提供一份详尽的指南,帮助......
  • AI 助力,歌词创作不再是难题
    在音乐的世界里,歌词创作一直被视为一项充满挑战和灵感的艺术工作。然而,随着科技的飞速发展,AI技术的出现正在悄然改变这一局面,让曾经困扰众多创作者的难题迎刃而解。“妙笔生词智能写歌词软件(53650899)”便是这股科技浪潮中的杰出代表。它以强大的AI能力为基石,为广大音乐爱好者......
  • 大型企业如何整合集成全域数据、解决数据孤岛难题?
    今天,我们说一下大型企业全域数据的整合集成问题。通常,中大型企业和集团公司拥有大量多源异构的数据存储资源,如数据仓库、数据湖以及分布于分子公司和混合多云平台的业务系统,通过传统物理集中统一数据资产管理的方式难度高,代价大,这就带来一系列问题:数据孤岛普遍存在,包括随着业......
  • 《尘埃4》游戏启动难题:msvcp100.dll缺失的全方位修复指南
    当您兴致勃勃地准备在《尘埃4》(DiRT4)中驰骋赛道,却突然遭遇“找不到msvcp100.dll文件”的错误提示时,这无疑是对游戏热情的一种打击。msvcp100.dll是MicrosoftVisualC++2010运行库的一部分,许多现代游戏和应用程序依赖于它才能正常运行。本文将详细介绍几种有效的方法来解决这......
  • 守护舌尖安全,破解EHS管理难题,食品加工企业的可持续发展之路
    在当今社会,食品安全与环境保护已成为全球关注的热点,食品加工企业作为连接农业与消费者的关键环节,其环境、健康与安全(EHS)管理水平直接关系到产品的质量和企业的可持续发展。然而,食品加工企业在EHS管理方面面临着诸多痛点,构建一套完善的EHS管理体系显得尤为重要。一、食品加工企......