题解 【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+桶+树上差分",但这篇题解是为了让很多很多看了很多题解仍然看不懂的朋友们看懂的,其中就包括我,我也在努力地把解题的"思维 ...
随机推荐
- Translent关键字-InvalidClassException异常_原理和解决方案
Translent关键字 static关键字:静态关键字静态优先于非静态加载到内存中(静态优先于对象进入到内存中)被static修饰的成员变量不能被序列化的,序列化的都是对象private stati ...
- 同时打开多个.exe文件怎么解决
同时打开多个.exe文件怎么解决 小黑最近遇到一个问题,就是Unity封装好用来直接打开.exe的函数不好用了!! 怎么解决? 于是发现了.bat文件!好用至极啊 前提 小黑是征求过客户同意之后才这么 ...
- 如何修剪git reflog历史
背景: vscode插件git-graph可以方便查看git-commit-graph,效果很好,关键是交互性很好.点选任意commit即可预览提交内容,实在是太方便了,比我之前用命令行上git lo ...
- 使用 flexible.js + rem 制作苏宁移动端首页
一.技术选型 二.搭建相关文件夹 三.设置视口标签以及引入初始化样式文件和js文件 四.body 样式 五.rem 适配方案二 body样式修改 index.css body { min-width: ...
- vulnhub靶场渗透实战15-matrix-breakout-2-morpheus
vulnhub靶场渗透实战15-matrix-breakout-2-morpheus 靶机搭建:vulnhub上是说vbox里更合适.可能有vbox版本兼容问题,我用的vmware导入. 靶场下载地址 ...
- supervisor管理java进程
安装 yum install supervisor 设置开机启动 systemctl enable supervisord 启动supervisord systemctl start supervis ...
- VUE10 计算属性
1 Vue计算属性简介 1)定义:我们需要一个属性,但是这个属性不存在,但是可以通过已有的属性计算得来,那么就可以定义一个计算属性. 2)原理:底层借助了Object.defineproperty方法 ...
- .Net Core后端架构实战【1-项目分层框架设计】
摘要:基于.NET Core 7.0WebApi后端架构实战[1-项目结构分层设计] 2023/02/05, ASP.NET Core 7.0, VS2022 引言 从实习到现在回想自己已经入行四年 ...
- (二) MdbCluster分布式内存数据库——分布式架构1
(二) MdbCluster分布式内存数据库--分布式架构1 分布式架构是MdbCluster的核心关键,业界有很多相关的实现,却很少有文章详细的解释每个架构实现背后的细节和这么做的原因.在Mdb ...
- JZOJ 2020.07.27【NOIP提高组】模拟
总结 今天的题还好,不幸拿了 \(rank1\),只有 \(380pts\) 实际 \(AK\) 也不难 前三题都是思维题 后面一题其实不过是简单的数据结构优化 \(dp\) 的题 用 \(GSM\) ...