题解 【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+桶+树上差分",但这篇题解是为了让很多很多看了很多题解仍然看不懂的朋友们看懂的,其中就包括我,我也在努力地把解题的"思维 ...
随机推荐
- Unity之Android端权限申请
Unity之Android端权限申请 Unity之Android端权限申请 前言 开篇废话 Unity版本 正题 前期准备 挂载脚本 打包发布 安装App 查看结果 结尾 唠家常 今日无推荐 Unit ...
- python语法进阶这一篇就够了
前言 前面我们已经学习了Python的基础语法,了解了Python的分支结构,也就是选择结构.循环结构以及函数这些具体的框架,还学习了列表.元组.字典.字符串这些Python中特有的数据结构,还用这些 ...
- c++ stl 详解 csp备考
最近在准备csp认证考试,打算使用c++语言,以下是关于c++ stl库的内容: algorithm概览(作者:当格子衫爱上Helloworld) stl库详解(作者:c语言中文网) https:// ...
- pip和pipenv简记
一. pip篇 1. 配置文件换源 windows:C:\Users\Administrator\pip\pip.ini mac:~/pip/pip.conf [global] index-url = ...
- 题解 [SCOI2008]斜堆
好题.一道很有趣的性质提. 因为自己搞错结论然后改了 1h(悲 闲话少说,切入正题-- 这是不断插入的,所以根据套路我们会考虑最后一个插入的节点的性质.显然满足: 它是从根不停往左走的路上. 它没有右 ...
- CCRD总目录(2007年至今,动态更新中)
中信国健临床通讯总目录 (动态更新.末次更新: 2015-07-06) 年份 目录网址 2010年 1.2010年第01期 (或者浏览有备注的目录: 2010年第01期 ) 2. 2010年第02期 ...
- ELK 一些截图
一.背景 集成环境中,多台服务器会存在多份日志,不方便查阅 · 二.原理 三.配置原理 Logstash是安装在服务器上的,相当于读取本地日志,然后输出到ES服务器,kibana会从ES服务器读取数据 ...
- JavaWeb中的Servlet
Servlet 目录 Servlet 一.互联网中的资源 二.Servlet 2.1.Servlet的作用 2.2.Servlet执行流程 2.3.Servlet生命周期 2.4.Servlet的继承 ...
- SpringBoot常用注解大全
常用注解概览 这里整理了一张SpringBoot常用注解的思维导图,本文主要讲解这些注解的用法. 组件相关注解 @ComponentScan 默认扫描当前包及其子包下面被@component,@Con ...
- WPF使用WindowChrome自定义标题栏
第一步:基本实现 添加Window的Style定义,并设置WindowChrome.WindowChrome属性: 设置WindowChrome标题栏: CaptionHeight--主要用于拖动有效 ...