题意:一棵树有N个城市,每个城市商品价格不一样,Q个询问,问从u出发到达v点,每个城市只能经过一次的最大利润

max min数组存u城到u的第2^i个祖先路径上的最值

答案就是u-v路径上的最大值-最小值

真的是这样吗?

仔细想想,买入点可能在卖出点之后吗?当然不行

于是把路径分成两段

问题就变成下列三种情况

购买和卖出都在A段中完成

购买和卖出都在B段中完成

在A段中购买,B段中卖出

然后将A,B段分别进行处理(感觉像是dp的思想)

这还不够,还要分方向进行处理

shun【u】表示从u往LCA走 dao【u】表示从LCA往u走

最后别忘了处理U-LCA购买,LCA-V卖出的情况

#include<cstdio>
#define inf 0x3f3f3f3f
#define N 50005 int n,q,a,b;
int cnt;
int val[N],head[N],dep[N];
int f[N][21],mx[N][21],mn[N][21],shun[N][21],dao[N][21]; void inline swap(int &a,int &b){
a^=b^=a^=b;
} inline int max(int x,int y){
if(x>y) return x;
return y;
} inline int min(int x,int y){
if(x<y) return x;
return y;
} struct node{
int v,nex;
}e[N*2]; inline void add(int u,int v){
cnt++;
e[cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
} inline void dfs(int u,int fa){
dep[u]=dep[fa]+1;
f[u][0]=fa;
mx[u][0]=max(val[u],val[fa]);
mn[u][0]=min(val[u],val[fa]);
shun[u][0]=max(0,val[fa]-val[u]);
dao[u][0]=max(0,val[u]-val[fa]);
for(register int i=1;i<=20;++i){
f[u][i]=f[f[u][i-1]][i-1];
mx[u][i]=max(mx[u][i-1],mx[f[u][i-1]][i-1]);
mn[u][i]=min(mn[u][i-1],mn[f[u][i-1]][i-1]);
int k=mx[f[u][i-1]][i-1]-mn[u][i-1];
int p=mx[u][i-1]-mn[f[u][i-1]][i-1];
shun[u][i]=max(k,max(shun[u][i-1],shun[f[u][i-1]][i-1]));
dao[u][i]=max(p,max(dao[u][i-1],dao[f[u][i-1]][i-1]));
}
for(register int i=head[u];i;i=e[i].nex){
int v=e[i].v;
if(v==fa) continue;
dfs(v,u);
}
} inline int lca(int a,int b){
int ans=0,Max=0,Min=0x3f3f3f3f;
Max=val[b],Min=val[a];
if(dep[a]<dep[b]){
for(register int i=20;i>=0;--i){
if(dep[a]>dep[f[b][i]]) continue;
ans=max(ans,max(Max-mn[b][i],dao[b][i]));
Max=max(Max,mx[b][i]);
b=f[b][i];
}
}
else{
for(register int i=20;i>=0;--i){
if(dep[b]>dep[f[a][i]]) continue;
ans=max(ans,max(mx[a][i]-Min,shun[a][i]));
Min=min(Min,mn[a][i]);
a=f[a][i];
}
}
if(a==b) return ans;
for(register int i=20;i>=0;--i){
if(f[b][i]==f[a][i]) continue;
ans=max(ans,max(mx[a][i]-Min,shun[a][i]));
ans=max(ans,max(Max-mn[b][i],dao[b][i]));
Max=max(Max,mx[b][i]);
Min=min(Min,mn[a][i]);
a=f[a][i];
b=f[b][i];
}
ans=max(ans,shun[a][0]);
ans=max(ans,dao[b][0]);
Max=max(Max,mx[b][0]);
Min=min(Min,mn[a][0]);
ans=max(ans,Max-Min);
return ans;
} int main(){
// freopen("1.in","r",stdin);
// freopen("E.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&val[i]);
}
for(int i=1;i<n;++i){
scanf("%d%d",&a,&b);
add(a,b);add(b,a);
}
dfs(1,0);
scanf("%d",&q);
for(int i=1;i<=q;++i){
scanf("%d%d",&a,&b);
printf("%d\n",lca(a,b));
}
getchar();
return 0;
}

题解 【POJ3728】The merchant(LCA)的更多相关文章

  1. POJ3728 THE MERCHANT LCA RMQ DP

    题意简述:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. ...

  2. poj3728 倍增法lca 好题!

    lca的好题!网上用st表和离线解的比较多,用树上倍增也是可以做的 不知道错在哪里,等刷完了这个专题再回来看 题解链接https://blog.csdn.net/Sd_Invol/article/de ...

  3. POJ3728 The merchant解题报告

    Description There are N cities in a country, and there is one and only one simple path between each ...

  4. [POJ3728]The merchant

    题目大意: 给你一棵n个结点的带权树,有q组询问,问你从u到v的路径上最大值与最小值的差(最大值在最小值后面). 思路: 首先考虑路径上合并两个子路径u->t和t->v时的情况. 假设我们 ...

  5. poj3728之离线LCA+dp思想/RMQ+LCA(非常好的题目)

    题意很简单 给一个树(n < 5w) 每个点有个权值,代表商品价格 若干个询问(5w) 对每个询问,问的是从u点走到v点(简单路径),商人在这个路径中的某点买入商品,然后在某点再卖出商品,   ...

  6. [POJ3728]The merchant(tanrjan_lca + DP)

    传送门 比着题解写还错... 查了两个小时没查出来,心态爆炸啊 以后再查 ——代码(WA) #include <cstdio> #include <cstring> #incl ...

  7. poj3728 The merchant[倍增]

    给一棵点带权树,$q$次询问,问树上$x$到$y$路径上,两点权之差(后面的减去前面的)的最大值. 这个是在树链上找点,如果沿路径的最小值在最大值之前出现那肯定答案就是$maxx-minx$,但是反之 ...

  8. 【BZOJ2588】Count on a tree 题解(主席树+LCA)

    前言:其实就是主席树板子啦……只不过变成了树上的查询 -------------------------- 题目链接 题目大意:求树上$u$到$v$路径第$k$大数. 查询静态区间第$k$大肯定是用主 ...

  9. 【转】Tarjan&LCA题集

    转自:http://blog.csdn.net/shahdza/article/details/7779356 [HDU][强连通]:1269 迷宫城堡 判断是否是一个强连通★2767Proving ...

  10. NOIP2016(D1T2)天天爱跑步题解

    首先声明这不是一篇算法独特的题解,仍然是"LCA+桶+树上差分",但这篇题解是为了让很多很多看了很多题解仍然看不懂的朋友们看懂的,其中就包括我,我也在努力地把解题的"思维 ...

随机推荐

  1. Java入门与进阶P-4.5+P-4.6

    逻辑类型 关系运算的结果是要给逻辑值,true或false.这个值可以保存在一个对应的逻辑类型变量中,这样的变量类型是boolean 布尔是为了纪念George Boole对逻辑计算得到贡献 bool ...

  2. 10分钟搞定简易MVVM

    实现一个简易的 MVVM 分为这么几步来 1.类 Vue:这个类接收的是一个 options. el属性:根元素的id data属性:双向绑定的数据. 2.Dep 类: subNode数组:存放所依赖 ...

  3. reids(2)概述与安装

    前言 redis安装在Linux服务器上,系统为centos7,安装的版本为redis6.2.10 下载与安装 下载地址:https://redis.io/download/#redis-downlo ...

  4. 图论之最短路径 Floyd算法

    /** 图论之最短路径 Floyd算法 */ #include<stdio.h> #include<string.h> #include<algorithm> #d ...

  5. 代码随想录算法训练营day18 | leetcode 513.找树左下角的值 ● 112. 路径总和 113.路径总和ii ● 106.从中序与后序遍历序列构造二叉树

    LeetCode 513.找树左下角的值 分析1.0 二叉树的 最底层 最左边 节点的值,层序遍历获取最后一层首个节点值,记录每一层的首个节点,当没有下一层时,返回这个节点 class Solutio ...

  6. jsHtml解码

    //将HTML代码转换为文本 function HTMLDecode(text) { var temp = document.createElement("div"); temp. ...

  7. RocketMQ 5.0 vs 4.9.X 图解架构对比

    本文作者:李伟,Apache RocketMQ Committer,RocketMQ Python客户端项目Owner ,Apache Doris Contributor,腾讯云数据库开发工程师. 0 ...

  8. KingbaseES DBLink 介绍

    DBLink 扩展插件功能与 Kingbase_FDW 类似,用于远程访问KingbaseES 数据库.相比于Kingbase_FDW,DBLink 功能更强大,可以执行DML,还可以通过 begin ...

  9. JZOJ 6664. 【2020.05.28省选模拟】最优化

    \(\text{Solution}\) 原题:\(\text{Honorable Mention}\) 一个费用流做法,\(S\) 向 \(2i-1\) 连流量为 \(1\),费用为 \(0\) 的边 ...

  10. 关于cnpm的卸载与重装

    1.卸载原有旧的版本: npm uninstall -g cnpm --registry=https://registry.npm.taobao.org 2.注册模块镜像: npm set regis ...