CF1000G Two-Paths
题目大意:给你一棵树,其中点上和边上都有值。定义2-Path为经过一条边最多两次的路径,价值为经过点的权值加和-经过边权值*该边经过次数。4e5组询问,每次询问树上连接x,y两点的2-Path的最大价值。
先说一句:
机房中认为图画的最好:https://blog.csdn.net/lleozhang/article/details/83659914
题解:
一道状态比较多的树形dp。
dp1:记录x点子树内从x到x的最大2-Path的价值-x的值。
dp2:记录从fa[x]到fa[x]不经过x且不经过fa[fa[x]]的最大2-Path价值-fa[x]的值。
dp3:记录从fa[x]到fa[x]不经过x的任意儿子的2-Path的价值-x的值。
(描述比较恶心,见图)

(图也比较恶心)
红色的边和涂黑的未知物体都要取。
然后还有比较大众的ds1:记录x到根的点权之和,和ds2:记录x到根的边权之和。
还要求一下每个点到根节点经过点的dp2之和。
dfsO(n)搞dp,询问O(nlogn)。
比描述和图片更恶心的代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 300050
#define Q 400050
#define ll long long
int n,q,hed[N],cnt;
struct EG
{
int to,nxt;
ll val;
}e[*N];
void ae(int f,int t,ll v)
{
e[++cnt].to = t;
e[cnt].val = v;
e[cnt].nxt = hed[f];
hed[f] = cnt;
}
ll a[N];
int dep[N],fa[N][];
ll ds1[N],ds2[N],E[N];
void dfs1(int u,int f)
{
dep[u]=dep[f]+;
for(int j=hed[u];j;j=e[j].nxt)
{
int to = e[j].to;
if(to==f)continue;
fa[to][]=u;
E[to]=e[j].val;
ds1[to]=ds1[u]+a[to];
ds2[to]=ds2[u]+e[j].val;
dfs1(to,u);
}
}
int get_lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=;i>=;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y)return x;
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][];
}
ll dp1[N],dp2[N];
bool vis[N];
void dfs(int u)
{
for(int j=hed[u];j;j=e[j].nxt)
{
int to = e[j].to;
if(to==fa[u][])continue;
dfs(to);
if(dp1[to]+a[to]-2ll*e[j].val>=)
{
dp1[u]+=dp1[to]+a[to]-2ll*e[j].val;
vis[to]=;
}
}
for(int j=hed[u];j;j=e[j].nxt)
{
int to = e[j].to;
if(to==fa[u][])continue;
if(!vis[to])dp2[to]=dp1[u];
else dp2[to]=dp1[u]-(dp1[to]+a[to]-2ll*e[j].val);
}
}
ll dp3[N],sum2[N];
void Dfs(int u)
{
sum2[u]+=dp2[u];
for(int j=hed[u];j;j=e[j].nxt)
{
int to = e[j].to;
if(to==fa[u][])continue;
sum2[to]+=sum2[u];
dp3[to]=max(0ll,dp3[u]+1ll*a[u]+dp2[to]-2ll*e[j].val);
Dfs(to);
}
}
ll sol(int x,int y)
{
if(dep[x]>dep[y])swap(x,y);
int lca = get_lca(x,y);
if(x==lca)
{
return dp3[x]+dp1[y]+sum2[y]-sum2[x]+(ds1[x]+ds1[y]-ds1[lca]-ds1[fa[lca][]])-(ds2[x]+ds2[y]-2ll*ds2[lca]);
}else
{
int ffx = x,ffy = y;
for(int i=;i>=;i--)
{
if(dep[fa[ffx][i]]>dep[lca])
ffx=fa[ffx][i];
if(dep[fa[ffy][i]]>dep[lca])
ffy=fa[ffy][i];
}
return dp1[x]+dp1[y]+sum2[x]+sum2[y]-sum2[ffx]-sum2[ffy]+dp3[lca]+dp2[ffx]-(vis[ffy]==)*(dp1[ffy]+a[ffy]-2ll*E[ffy])+(ds1[x]+ds1[y]-ds1[lca]-ds1[fa[lca][]])-(ds2[x]+ds2[y]-2ll*ds2[lca]);
}
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++)scanf("%lld",&a[i]);
ll v;
for(int f,t,i=;i<n;i++)
{
scanf("%d%d%lld",&f,&t,&v);
ae(f,t,v),ae(t,f,v);
}
ds1[]=a[];
dfs1(,);
for(int k=;k<=;k++)
for(int i=;i<=n;i++)
fa[i][k]=fa[fa[i][k-]][k-];
dfs();
Dfs();
for(int x,y,i=;i<=q;i++)
{
scanf("%d%d",&x,&y);
printf("%lld\n",sol(x,y));
}
return ;
}
CF1000G Two-Paths的更多相关文章
- [LeetCode] Binary Tree Paths 二叉树路径
Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 ...
- [LeetCode] Unique Paths II 不同的路径之二
Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...
- [LeetCode] Unique Paths 不同的路径
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...
- leetcode : Binary Tree Paths
Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 ...
- UVA 10564 Paths through the Hourglass[DP 打印]
UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...
- LeetCode-62-Unique Paths
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...
- Leetcode Unique Paths II
Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...
- POJ 3177 Redundant Paths(边双连通的构造)
Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13717 Accepted: 5824 ...
- soj 1015 Jill's Tour Paths 解题报告
题目描述: 1015. Jill's Tour Paths Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description Every ...
- Unique Paths II
这题在Unique Paths的基础上增加了一些obstacle的位置,应该说增加的难度不大,但是写的时候对细节的要求多了很多,比如,第一列的初始化会受到之前行的第一列的结果的制约.另外对第一行的初始 ...
随机推荐
- ChartCtrl源码剖析之——CChartGrid类
CChartGrid类用来绘制波形区域中的表格,当绘制波形时波形就显示在这些表格上面.它处于该控件的区域,如下图所示: CChartGrid类的头文件. #if !defined(AFX_CHARTG ...
- 使用 SQL Server Management Studio的活动和监视器 查看运行的SQL语句
使用SQL Server Management Studio可以查看SQL Server 服务器执行的SQL语句,支持sql server,(LocalDB)\V11.0,Projects\v12和s ...
- E20180306-hm-xa
base n. 基地; 基础; 根据; 基数(如十进制的10 和二进制的2) designate vt. 指派; 指明,指出; 表明,意味着; 把…定名为;
- Java中关键字continue、break和return的区别
Java中关键字continue.break和return的区别: continue:跳出本次循环继续下一次循环 break: 跳出循环体,继续执行循环外的函数体 return: 跳出整个函数 ...
- jQuery html操作
jQuery 拥有可操作 HTML 元素和属性的强大方法. jQuery DOM 操作 DOM = Document Object Model(文档对象模型) jQuery 中非常重要的部分,就是操作 ...
- [ZOJ1961]Let it Bead
Description "Let it Bead" company is located upstairs at 700 Cannery Row in Monterey, CA. ...
- Tian Ji -- The Horse Racing HDU - 1052
Tian Ji -- The Horse Racing HDU - 1052 (有平局的田忌赛马,田忌赢一次得200块,输一次输掉200块,平局不得钱不输钱,要使得田忌得到最多(如果只能输就输的最少) ...
- java.lang.UnsatisfiedLinkError: E:\TomcatV7_iot\bin\tcnative-1.dll: Can't load AMD 64-bit .dll on a IA 32-bit platform
启动64位Tomcatv7时报如下错误: java.lang.UnsatisfiedLinkError: E:\TomcatV7_iot\bin\tcnative-.dll: Can't load A ...
- Android 内存溢出处理方案
转自 : http://www.cnblogs.com/hello-ruby/archive/2013/04/19/3031098.html 首先我们来看看android内存溢出的原因,有可能是: 由 ...
- 总结用CoreText绘制文本时遇到的问题以及解决办法
关于CoreText不做解释.用的人自然知道这个是干什么的. 功能非常强大,可以绘制文本,图片等. 这次用的Xcode7.0的版本.所以之前很多方法,现在不能用.也不是不能用,就是有黄色警告很不爽. ...