题目:https://vjudge.net/contest/323605#problem/E

题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i<j)a[j]-a[i]的最大值,j必须是u->v路径上出现的比i晚

思路:首先我们路径肯定是确定只有一条的,然后我们怎么找出那条路径呢,我们可以求LCA,求出u->LCA(u,v)   LCA(u,v)->v  ,这样我们就能把路径给确定出来

然后我们先简化问题,如果是一个序列,我们要找两个数的最大差值,我们可以维护一个单调栈,然后每次求最大差值,复杂度为O(n),我们可以先用LCA把路径求出来,然后直接O(n)遍历出来即可,但是查询数量有 <=50000,会超时,这个时候我们只能想能不能预处理一些有用的东西,然后O(1)查询出来,因为LCA复杂度为O(logn)*(O(m)查询数)复杂度正好,我们可以优化上述算法,首先我们肯定和最大值最小值有关,我们求出每个点到LCA的最小值,和LCA到当前点的最大值,然后如何练习起来呢,其实我们可以把路径合并,首先两个点之间间隔一条边,肯定就是max(value[v]-value[u],0),然后合并的时候有一个转移方程,max(u->LCA(u,v)的利润,LCA(u,v)->v的利润,max(LCA(u,v)->v)-min(u,LCA(u,v))   ), 为什么呢下面给出三个例子

例子一,这个就是用maxvalue-minvalue

例子二,这个就是u->LCA(u,v)情况

例子三,这个就是LCA(u,v)->v的情况

然后差不多就可以解出来了,因为本人对LCA还不会太操作,然后就没写代码了,发现自己思路是对的,就直接贴别人代码了>_<

来源:https://blog.csdn.net/xingyeyongheng/article/details/20402603

/*分析:先求出点u,v的最近公共祖先f,然后求u->f->v的利润最大值maxval
对于这个maxval可能有三种情况:
1:maxval是u->f的maxval
2:maxval是f->v的maxval
3:maxval是u->f的最小w[i]减去f->v的最大w[i]
分析到这很明显需要设置4个变量来求maxval:
up[u]表示u->f的最大maxval
down[u]表示f->u的最大maxval
maxw[u]表示u-f的最大w[i]
minw[u]表示u-f的最小w[i]
所以maxval=max(max(up[u],down[v]),maxw[v]-minw[u]);
现在问题就是如何快速的求出这四个变量,在这里我们可以对u,v的LCA(u,v)进行分类解决
对于LCA(u,v)是f的询问全部求出,然后再求LCA(u,v)是f的父亲的询问
这样当我们求LCA(u,v)是f的父亲的询问的时候就可以借用已经求出的LCA(u,v)是f的询问
的结果,这样就不用反复去求u->f的那四个变量值,u->father[f]也能快速求出
这个变化主要在寻找father[v]这个过程中进行,具体看代码
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <map>
#include <cmath>
#include <iomanip>
#define INF 99999999
typedef long long LL;
using namespace std; const int MAX=+;
int n,m,size;
int uu[MAX],vv[MAX],ww[MAX],sum[MAX];
int up[MAX],down[MAX],maxw[MAX],minw[MAX],father[MAX];
int head[MAX],head2[MAX],head3[MAX];
bool mark[MAX]; struct Edge{
int v,id,next;
Edge(){}
Edge(int V,int ID,int NEXT):v(V),id(ID),next(NEXT){}
}edge[MAX*],edge2[MAX*],edge3[MAX*]; void Init(int num){
for(int i=;i<=num;++i)head[i]=head2[i]=head3[i]=-,mark[i]=false;
size=;
} void InsertEdge(int u,int v,int id){
edge[size]=Edge(v,id,head[u]);
head[u]=size++;
} void InsertEdge2(int u,int v,int id){
edge2[size]=Edge(v,id,head2[u]);
head2[u]=size++;
} void InsertEdge3(int u,int v,int id){
edge3[size]=Edge(v,id,head3[u]);
head3[u]=size++;
} int findset(int v){
if(v == father[v])return father[v];
int fa=father[v];
father[v]=findset(father[v]);
up[v]=max(max(up[v],up[fa]),maxw[fa]-minw[v]);
down[v]=max(max(down[v],down[fa]),maxw[v]-minw[fa]);
maxw[v]=max(maxw[v],maxw[fa]);
minw[v]=min(minw[v],minw[fa]);
return father[v];
} void LCA(int u){
mark[u]=true;
father[u]=u;
for(int i=head2[u];i != -;i=edge2[i].next){//对LCA(u,v)进行分类
int v=edge2[i].v,id=edge2[i].id;
if(!mark[v])continue;
int f=findset(v);
InsertEdge3(f,v,id);
}
for(int i=head[u];i != -;i=edge[i].next){
int v=edge[i].v;
if(mark[v])continue;
LCA(v);
father[v]=u;
}
for(int i=head3[u];i != -;i=edge3[i].next){
int id=edge3[i].id;
findset(uu[id]);
findset(vv[id]);
sum[id]=max(max(up[uu[id]],down[vv[id]]),maxw[vv[id]]-minw[uu[id]]);
}
} int main(){
int u,v;
while(~scanf("%d",&n)){
Init(n);
for(int i=;i<=n;++i){
scanf("%d",ww+i);
up[i]=down[i]=;
maxw[i]=minw[i]=ww[i];
}
for(int i=;i<n;++i){
scanf("%d%d",&u,&v);
InsertEdge(u,v,i);
InsertEdge(v,u,i);
}
size=;
scanf("%d",&m);
for(int i=;i<m;++i){
scanf("%d%d",&uu[i],&vv[i]);
InsertEdge2(uu[i],vv[i],i);
InsertEdge2(vv[i],uu[i],i);
}
size=;
LCA();
for(int i=;i<m;++i)printf("%d\n",sum[i]);
}
return ;
}

POJ 3728 The merchant (树形DP+LCA)的更多相关文章

  1. poj 2324 Anniversary party(树形DP)

    /*poj 2324 Anniversary party(树形DP) ---用dp[i][1]表示以i为根的子树节点i要去的最大欢乐值,用dp[i][0]表示以i为根节点的子树i不去时的最大欢乐值, ...

  2. poj3417 Network 树形Dp+LCA

    题意:给定一棵n个节点的树,然后在给定m条边,去掉m条边中的一条和原树中的一条边,使得树至少分为两部分,问有多少种方案. 神题,一点也想不到做法, 首先要分析出加入一条边之后会形成环,形成环的话,如果 ...

  3. hdu_5293_Tree chain problem(DFS序+树形DP+LCA)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5293 被这题打蹦了,看着题解写的,很是爆炸,确实想不到,我用的DFS序+LCA+树形DP,当然也可以写 ...

  4. POJ 3162.Walking Race 树形dp 树的直径

    Walking Race Time Limit: 10000MS   Memory Limit: 131072K Total Submissions: 4123   Accepted: 1029 Ca ...

  5. POJ 1655.Balancing Act 树形dp 树的重心

    Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14550   Accepted: 6173 De ...

  6. POJ 2342 - Anniversary party - [树形DP]

    题目链接:http://poj.org/problem?id=2342 Description There is going to be a party to celebrate the 80-th ...

  7. POJ - 3162 Walking Race 树形dp 单调队列

    POJ - 3162Walking Race 题目大意:有n个训练点,第i天就选择第i个训练点为起点跑到最远距离的点,然后连续的几天里如果最远距离的最大值和最小值的差距不超过m就可以作为观测区间,问这 ...

  8. POJ 2486 Apple Tree(树形DP)

    题目链接 树形DP很弱啊,开始看题,觉得貌似挺简单的,然后发现貌似还可以往回走...然后就不知道怎么做了... 看看了题解http://www.cnblogs.com/wuyiqi/archive/2 ...

  9. POJ 3162 Walking Race 树形DP+线段树

    给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成 ...

  10. POJ 1849 - Two - [DFS][树形DP]

    Time Limit: 1000MS Memory Limit: 30000K Description The city consists of intersections and streets t ...

随机推荐

  1. postman连接mysql执行操作

    postman也可以连接mysql 目录 1.安装 2.启动服务 3.执行sql语句 1.安装 想要postman连接mysql,需要安装xmysql,启动该服务,然后才可以调用. 预置条件:完成no ...

  2. R语言CSV文件

    R语言CSV文件 在R语言中,我们可以从存储在R环境外部的文件读取数据.还可以将数据写入由操作系统存储和访问的文件. R可以读取和写入各种文件格式,如:csv,excel,xml等. 在本章中,我们将 ...

  3. java RMI 远程调用

    1.背景 在学习代理模式的过程中接触到了远程调用,jdk有自己的RMI实现,所以这边自己实现了RMI远程调用,并记录下心得. 感受最深的是RMI和现在的微服务有点相似,都是通过"注册中心&q ...

  4. Docker中使用多阶段Dockerfile构建容器镜像image(镜像优化)

    使用多阶段构建 预计阅读时间: 6分钟 多阶段构建是守护程序和客户端上需要Docker 17.05或更高版本的新功能.多阶段构建对于那些努力优化Dockerfiles同时使其易于阅读和维护的人来说非常 ...

  5. 从SVN下检出项目内容【步骤】

    1.新创建一个新的工作环境,然后new--->other--->SVN 2.点击Next,然后进行检出项目的操作,如下图所示: 3.再点击Next,进行输入指定的url地址,从指定的url ...

  6. JavaScript ES6中export、import与export default的用法和区别

    前言 相信很多人都使用过export.export default.import,然而它们到底有什么区别呢? 在看他们之间的区别之前,我们先来看看它们的用法. ES6 import和export的用法 ...

  7. Keyboarding (bfs+预处理+判重优化)

    # #10030. 「一本通 1.4 练习 2」Keyboarding [题目描述] 给定一个 $r$ 行 $c$ 列的在电视上的"虚拟键盘",通过「上,下,左,右,选择」共 $5 ...

  8. mongoDB关系型数据库的对比

    一.基本操作 1.mongoDB和关系型数据库对比 对比项 mongoDB mysql oracle 表 集合list 二维表 表的一行数据 文档document 一条记录 表字段 键key 字段fi ...

  9. 你的package包名有问题!

    今天在Eclipse中运行我的Java程序中,就弹出了以下消息的窗口: 注意窗口的名字为Java Virtual Machine Launcher . Error : A JNI error has ...

  10. Docker实战部署应用——MySQL5.7

    MySQL 部署 拉取MySQL镜像 拉取命令: docker pull mysql:5.7 查看镜像 docker images 创建 MySQL 容器 docker run -id --name= ...