题目大意:给你一棵树,其中点上和边上都有值。定义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的更多相关文章

  1. [LeetCode] Binary Tree Paths 二叉树路径

    Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 ...

  2. [LeetCode] Unique Paths II 不同的路径之二

    Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...

  3. [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 ...

  4. leetcode : Binary Tree Paths

    Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 ...

  5. UVA 10564 Paths through the Hourglass[DP 打印]

    UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...

  6. 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 ...

  7. Leetcode Unique Paths II

    Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...

  8. POJ 3177 Redundant Paths(边双连通的构造)

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13717   Accepted: 5824 ...

  9. soj 1015 Jill's Tour Paths 解题报告

    题目描述: 1015. Jill's Tour Paths Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description Every ...

  10. Unique Paths II

    这题在Unique Paths的基础上增加了一些obstacle的位置,应该说增加的难度不大,但是写的时候对细节的要求多了很多,比如,第一列的初始化会受到之前行的第一列的结果的制约.另外对第一行的初始 ...

随机推荐

  1. 关于使用kafka时对于大数据消息体是遇到的问题

    kafka对于消息体的大小默认为单条最大值是1M. 但是在我们应用场景中, 常常会出现一条消息大于1M, 如果不对kafka进行配置. 则会出现生产者无法将消息推送到kafka或消费者无法去消费kaf ...

  2. UTF-8格式的文本文件程序读取异常

    最近在windows服务器上直接创建并手打输入配置参数,比如设置概率0.6,然后用java程序打开读取该参数,在本地linux环境下测试完全正常,但是一放到服务器上,就报NotNumber错误,查看了 ...

  3. mybatis-plus 获取新增id

    <insert id="insert" parameterType="com.xxx.xxxx.pojo.User"> insert into t_ ...

  4. bzoj1925 [Sdoi2010] 地精部落【DP】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1925 一个多月前“过”了这道题,还自欺欺人地认为懂了这道题,这直接导致了昨晚多校联测2的T3 ...

  5. C#内存映射文件学习[转]

    原文链接 内存映射文件是由一个文件到进程地址空间的映射. C#提供了允许应用程序把文件映射到一个进程的函(MemoryMappedFile.CreateOrOpen).内存映射文件与虚拟内存有些类似, ...

  6. MAT使用入门

    原文出处: 高建武 (Granker,@高爷) MAT简介 MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速.功能丰富的JAVA heap分析工具, ...

  7. Web常见几种攻击与预防方式

    DoS和DDoS攻击 DoS(Denial of Service),即拒绝服务,造成远程服务器拒绝服务的行为被称为DoS攻击.其目的是使计算机或网络无法提供正常的服务.最常见的DoS攻击有计算机网络带 ...

  8. ABP Zero最新版源码

    获取专业版源码  官网 学习版源码

  9. Farseer.net轻量级ORM开源框架 V1.2版本升级消息

    V1.1到V1.2的更新,重构了很多类及方法,其中主要做了性能优化(取消所有反射,使用表达式树+缓存).解耦了SQL生成层(没有实体.队列的依赖,所有数据均通过表达式树传递解析) 先上内部更新历史记录 ...

  10. 移动端使用页尾文字使用绝对定位遇到input框会飘起来的处理方案

    如下版权信息的样式在遇到input框的时候会跟随输入框其后 优雅的解决方式:(定位遇上键盘飘窗解决) mounted里面写上:var originalHeight=document.documentE ...