ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1000G Two-Paths&BSOJ6376【11.05模拟】草莓

2021-08-20 20:34:27  阅读:145  来源: 互联网

标签:Paths ch return fa 11.05 CF1000G int read dep


前言

这个题还有个加强版:BSOJ6376【11.05模拟】草莓

大概是人均场切了。

题目

CF1000G Two-Paths

分析

首先这个路径一定是一条链加上若干回路的路径。

每次 \(x\) 到 \(y\) 的途中都可以进入子树进行获取贡献,为了尽可能大,我们可以先 \(dp\) 出每一个点到子树再回来可以得到的最大贡献。

以及每一个点到父亲再回来可以得到的最大贡献。

再处理每一个点对父亲的 \(dp\) 值的贡献,那么每次询问就变成了询问路径和,使用树剖维护即可。

对于加强版就是还要考虑来回的路径值不同,这个可以前缀和一下解决。

代码

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
	while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
const int N=5e5+5;
#define ll long long
int n,a[N],q,idx;
int head[N],to[N<<1],val1[N<<1],val2[N<<1],nex[N<<1],fa[N][20],dep[N];
inline void add(int u,int v,int w1,int w2){
	nex[++idx]=head[u];
	to[idx]=v;
	head[u]=idx;
	val1[idx]=w1;
	val2[idx]=w2;
	return ;
}
ll dp[N],dp1[N],dpp[N],c[N],costd[N],costu[N],c1[N],num[N];
void dfs(int x,int f,int id){
	fa[x][0]=f;
	costd[x]=costd[f]+val1[id];costu[x]=costu[f]+val2[id];
	num[x]=num[f]+a[x];dep[x]=dep[f]+1;
	for(int i=1;i<20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
	dp[x]+=a[x];
	for(int i=head[x];i;i=nex[i]){
		int y=to[i];
		if(y==f) continue;
		dfs(y,x,i);
		dp[x]+=c[y];
	}
	c[x]=max(0ll,dp[x]-val1[id]-val2[id]);
	return ;
} 
void dfs1(int x,int f,int id){
	c1[x]=c1[f]+c[x];dpp[x]=dpp[f]+dp[x];
	dp1[x]=max(dp1[f]+dp[f]-c[x]-val1[id]-val2[id],0ll);
	for(int i=head[x];i;i=nex[i]){
		int y=to[i];
		if(y==f) continue;
		dfs1(y,x,i);
	}
//	cout<<x<<" costd:"<<costd[x]<<" costu:"<<costu[x]<<" num:"<<num[x]<<" c:"<<c[x]<<" dp:"<<dp[x]<<" dp1:"<<dp1[x]<<" dpp:"<<dpp[x]<<" c1:"<<c1[x]<<endl;
	
	return;
}
inline int Getlca(int u,int v){
	if(u==v) return u;
	if(dep[u]<dep[v]) swap(u,v);
	for(int i=19;i>=0;i--) if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
	if(u==v) return u;
	for(int i=19;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
	return fa[u][0];
}
inline int Jump(int x,int lca){
	for(int i=19;i>=0;i--) if(dep[fa[x][i]]>dep[lca]) x=fa[x][i];
	return x;
}
signed main(){
//	freopen("strawberry.in","r",stdin);
//	freopen("strawberry.out","w",stdout);
	read(n);read(q);
	for(int i=1;i<=n;i++) read(a[i]);
	for(int i=1;i<n;i++){
		int u,v,w1,w2;
		read(u),read(v),read(w1),w2=w1;
		add(u,v,w1,w2);
		add(v,u,w2,w1);
	}
	dfs(1,0,0);c[1]=0;
	dfs1(1,0,0);
	while(q--){
		int x,y;
		read(x),read(y);
		int lca=Getlca(x,y),ls=Jump(x,lca),rs=Jump(y,lca);
//		cout<<"LCA:"<<lca<<" ls:"<<ls<<" rs:"<<rs<<endl;
		if(x==lca) ls=0;
		if(y==lca) rs=0;
		ll Ans=0;
		if(x==y) Ans=dp[x]+dp1[x];
		else Ans=dpp[x]+dpp[y]-2*dpp[lca]+dp[lca]+dp1[lca]-(c1[x]+c1[y]-c1[lca]*2)-costu[x]+costu[lca]-costd[y]+costd[lca];
//		else Ans=dp[lca]+dp1[lca]-c[ls]-c[rs]-costu[x]+costu[lca]-costd[y]+costd[lca]+num[x]+num[y]-2*num[lca];
		write(Ans),putchar('\n');
	}
	return 0;
}

标签:Paths,ch,return,fa,11.05,CF1000G,int,read,dep
来源: https://www.cnblogs.com/Akmaey/p/15168039.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有