题目: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. 阿里云SLB产品HTTP、HTTPS、UDP协议使用

    1.http协议测试 第一步:添加http监听服务,前端端口为8080,后端端口为80,健康检查中检查端口为后端端口80: 第二步:在绑定的服务器上安装服务,步骤如下 centos系统中启动http协 ...

  2. 前端 CSS的选择器 伪类选择器

    伪类选择器 常用的几种伪类选择器. 伪类选择器一般会用在超链接a标签中 没有访问的超链接a标签样式: a:link { color: blue; } <!DOCTYPE html> < ...

  3. JavaSE编码试题强化练习3

    1.给20块钱买可乐,每瓶可乐3块钱,喝完之后退瓶子可以换回1块钱,问最多可以喝到多少瓶可乐. public class TestCirculation { public static void ma ...

  4. 循环结构 :while

    循环结构 :while 循环四要素: 1.初始化条件 2.循环条件 3.循环体 4.迭代条件 格式: 1.初始化条件 while(2.循环条件){ 3.循环体 4.迭代条件 } public clas ...

  5. stl应用

    http://codeforces.com/problemset/problem/1154/E E. Two Teams time limit per test 2 seconds memory li ...

  6. Gradle打包问题Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0

    前言 使用gradle打包react native的时候,出现了如下报错,下面和大家说一下解决的具体办法 Deprecated Gradle features were used in this bu ...

  7. vue数据响应式的一些注意点

    有关对象属性值不触发视图更新的情况: Vue 不能检测到对象属性的添加或删除,由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 ...

  8. Linux awk抓取IP的两种方式

    ip addr show ens33 | awk -F "[ /]+" '/inet /{print $3}' 或 ifconfig ens33 | awk -F "[ ...

  9. 《快学scala》读书笔记(1)

    第一章 基础 1.安装scala解释器 (1)scala-2.12.1.msi (2)配置环境变量:SCALA_HOME = D:\Program Files\scala Path= %SCALA_H ...

  10. NodeJS、npm安装步骤和配置(windows版本)

    https://jingyan.baidu.com/article/48b37f8dd141b41a646488bc.html 上面这个链接很详细了,怕它没了自己记一遍.我的简洁一点. 1. 打开no ...