题解 【POJ3728】The merchant(LCA)
题意:一棵树有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)的更多相关文章
- POJ3728 THE MERCHANT LCA RMQ DP
题意简述:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. ...
- poj3728 倍增法lca 好题!
lca的好题!网上用st表和离线解的比较多,用树上倍增也是可以做的 不知道错在哪里,等刷完了这个专题再回来看 题解链接https://blog.csdn.net/Sd_Invol/article/de ...
- POJ3728 The merchant解题报告
Description There are N cities in a country, and there is one and only one simple path between each ...
- [POJ3728]The merchant
题目大意: 给你一棵n个结点的带权树,有q组询问,问你从u到v的路径上最大值与最小值的差(最大值在最小值后面). 思路: 首先考虑路径上合并两个子路径u->t和t->v时的情况. 假设我们 ...
- poj3728之离线LCA+dp思想/RMQ+LCA(非常好的题目)
题意很简单 给一个树(n < 5w) 每个点有个权值,代表商品价格 若干个询问(5w) 对每个询问,问的是从u点走到v点(简单路径),商人在这个路径中的某点买入商品,然后在某点再卖出商品, ...
- [POJ3728]The merchant(tanrjan_lca + DP)
传送门 比着题解写还错... 查了两个小时没查出来,心态爆炸啊 以后再查 ——代码(WA) #include <cstdio> #include <cstring> #incl ...
- poj3728 The merchant[倍增]
给一棵点带权树,$q$次询问,问树上$x$到$y$路径上,两点权之差(后面的减去前面的)的最大值. 这个是在树链上找点,如果沿路径的最小值在最大值之前出现那肯定答案就是$maxx-minx$,但是反之 ...
- 【BZOJ2588】Count on a tree 题解(主席树+LCA)
前言:其实就是主席树板子啦……只不过变成了树上的查询 -------------------------- 题目链接 题目大意:求树上$u$到$v$路径第$k$大数. 查询静态区间第$k$大肯定是用主 ...
- 【转】Tarjan&LCA题集
转自:http://blog.csdn.net/shahdza/article/details/7779356 [HDU][强连通]:1269 迷宫城堡 判断是否是一个强连通★2767Proving ...
- NOIP2016(D1T2)天天爱跑步题解
首先声明这不是一篇算法独特的题解,仍然是"LCA+桶+树上差分",但这篇题解是为了让很多很多看了很多题解仍然看不懂的朋友们看懂的,其中就包括我,我也在努力地把解题的"思维 ...
随机推荐
- 流程概述与顺序结构-选择结构_单if语句
流程概述与顺序结构 概述 在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.也就是说,程序的流程对运行结果 有直接的影响.所以,我们必须清楚每条语句的执行流程.而且,很多时候我们要 ...
- C#如何提高代码质量(二)
多线程,异步,任务和并行 1.异步和多线程应用场景区分 多线程 计算密集型工作 异步 IO密集型工作 2.线城同步中使用信号量 EventWaitHandle AutoResetEvent Manua ...
- SQLSERVER 快照隔离级别 到底怎么理解?
一:背景 1. 讲故事 上一篇写完 SQLSERVER 的四个事务隔离级别到底怎么理解? 之后,有朋友留言问什么时候可以把 snapshot 隔离级别给补上,这篇就来安排,快照隔离级别看起来很魔法,不 ...
- 聊聊JUC包下的底层支撑类-AbstractQueuedSynchronizer(AQS)
聊聊JUC包下的底层支撑类-AbstractQueuedSynchronizer(AQS) juc包下的一堆并发工具类是我们日常开发特别是面试中常被拿来问的八股文之一,为了工作也好,为了面试也罢,今天 ...
- saas解决redis数据库分离的一种方案
package com.xf.config; import java.util.HashMap; import java.util.Map; import java.util.Set; import ...
- 不用Blazor WebAssembly,开发在浏览器端编译和运行C#代码的网站
本文中,我将会为大家分享一个如何用.NET技术开发"在浏览器端编译和运行C#代码的工具",核心的技术就是用C#编写不依赖于Blazor框架的WebAssembly以及Roslyn技 ...
- react 高效高质量搭建后台系统 系列 —— 表格的封装
其他章节请看: react 高效高质量搭建后台系统 系列 表格 有一种页面在后台系统中比较常见:页面分上下两部分,上部分是 input.select.时间等查询项,下部分是查询项对应的表格数据.包含增 ...
- evil 控制窗口大小,比快捷键方便
下面是vim原本的支持的键 可以用于 emacs evil ,evil 用这个比用快捷键还方面些 1.纵向调整 :res[ize] num 指定当前窗口为num列num行 :res[ize] +num ...
- 定位bug
软件测试阶段:单元测试,集成测试,系统测试,验收测试 测试人员参与的软件测试阶段一般来说只有集成测试和系统测试阶段.集成测试阶段主要测试的是接口:系统测试阶段主要是功能测试,兼容性测试等,涉及到定位b ...
- G - 逆序对的数量
G - 逆序对的数量 原题链接 什么是逆序对? 简单来说,两个数比较,下标小的数反而大,两个数称之为逆序对如\({3,1}\)就是这么一个逆序对 归并排序 由于逆序对逆序的性质,我们可以联想到排序: ...