[POJ 3728]The merchant
Description
There are N cities in a country, and there is one and only one simple path between each pair of cities. A merchant has chosen some paths and wants to earn as much money as possible in each path. When he move along a path, he can choose one city to buy some goods and sell them in a city after it. The goods in all cities are the same but the prices are different. Now your task is to calculate the maximum possible profit on each path.
Input
The first line contains N, the number of cities.
Each of the next N lines contains wi the goods' price in each city.
Each of the next N-1 lines contains labels of two cities, describing a road between the two cities.
The next line contains Q, the number of paths.
Each of the next Q lines contains labels of two cities, describing a path. The cities are numbered from 1 to N.
1 ≤ N, wi, Q ≤ 50000
Output
The output contains Q lines, each contains the maximum profit of the corresponding path. If no positive profit can be earned, output 0 instead.
Sample Input
4
1
5
3
2
1 3
3 2
3 4
9
1 2
1 3
1 4
2 3
2 1
2 4
3 1
3 2
3 4
Sample Output
4
2
2
0
0
0
0
2
0
题解
题解:因为没有修改,所以我们可以使用树上倍增来解决,
设 $fa[i][j]$表示点 $i$ 的第 $2^j$ 个祖先
$ma[i][j]$表示点 $i$ 到点 $fa[i][j]$的最大值。
$mi[i][j]$表示点 $i$ 到点 $fa[i][j]$的最小值。
$zma[i][j]$表示点 $i$ 到点 $fa[i][j]$的最大获利。
$fma[i][j]$表示点 $fa[i][j]$到点 $i$ 的最大获利。
然后我们可以预处理出这四个数组。
即:
ma[x][i]=max(ma[fa[x][i-]][i-],ma[x][i-]);
mi[x][i]=min(mi[fa[x][i-]][i-],mi[x][i-]);
zma[x][i]=max(max(zma[fa[x][i-]][i-],zma[x][i-]),ma[fa[x][i-]][i-]-mi[x][i-]);
fma[x][i]=max(max(fma[fa[x][i-]][i-],fma[x][i-]),ma[x][i-]-mi[fa[x][i-]][i-]);
在走向最近公共祖先的路径上记录一下历史最小值,在远离最近公共祖先的路径上记录一下历史最大值(在途中和最大获利比较)。最后答案再和历史最大值-历史最小值比较一下即可。
//It is made by Awson on 2017.10.13
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <string>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define LL long long
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
const int N = ;
const int INF = 1e9; int n, m, u, v, lim;
struct tt {
int to, next;
}edge[(N<<)+];
int path[N+], top;
int cost[N+];
int dep[N+], fa[N+][], maxn[N+][], minn[N+][], up[N+][], down[N+][]; void add(int u, int v) {
edge[++top].to = v;
edge[top].next = path[u];
path[u] = top;
}
void dfs(int u, int depth) {
dep[u] = depth;
for (int i = path[u]; i; i = edge[i].next)
if (dep[edge[i].to] == ) {
maxn[edge[i].to][] = Max(cost[edge[i].to], cost[u]);
minn[edge[i].to][] = Min(cost[edge[i].to], cost[u]);
up[edge[i].to][] = Max(, cost[u]-cost[edge[i].to]);
down[edge[i].to][] = Max(, cost[edge[i].to]-cost[u]);
fa[edge[i].to][] = u;
dfs(edge[i].to, depth+);
}
}
void ST() {
for (int t = ; t <= lim; t++)
for (int i = ; i <= n; i++) {
int v = fa[i][t-];
fa[i][t] = fa[v][t-];
maxn[i][t] = Max(maxn[i][t-], maxn[v][t-]);
minn[i][t] = Min(minn[i][t-], minn[v][t-]);
up[i][t] = Max(up[i][t-], up[v][t-]), up[i][t] = Max(up[i][t], maxn[v][t-]-minn[i][t-]);
down[i][t] = Max(down[i][t-], down[v][t-]), down[i][t] = Max(down[i][t], maxn[i][t-]-minn[v][t-]);
}
}
int get_lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int i = lim; i >= ; i--)
if (dep[fa[u][i]] >= dep[v])
u = fa[u][i];
if (u != v) {
for (int i = lim; i >= ; i--)
if (fa[u][i] != fa[v][i])
u = fa[u][i], v = fa[v][i];
u = fa[u][], v = fa[v][];
}
return u;
}
int get_ans(int u, int v) {
int lca = get_lca(u, v);
int ans = , large = -INF, small = INF;
for (int i = lim; i >= ; i--)
if (dep[fa[u][i]] >= dep[lca]) {
ans = Max(ans, up[u][i]);
ans = Max(ans, maxn[u][i]-small);
small = Min(small, minn[u][i]);
u = fa[u][i];
}
for (int i = lim; i >= ; i--)
if (dep[fa[v][i]] >= dep[lca]) {
ans = Max(ans, down[v][i]);
ans = Max(ans, large-minn[v][i]);
large = Max(large, maxn[v][i]);
v = fa[v][i];
}
return Max(ans, large-small);
} void work() {
scanf("%d", &n); lim = log(n*.)/log(*.);
for (int i = ; i <= n; i++) scanf("%d", &cost[i]);
for (int i = ; i < n; i++) {
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
dfs(, ); ST();
scanf("%d", &m);
while (m--) {
scanf("%d%d", &u, &v);
printf("%d\n", get_ans(u, v));
}
}
int main() {
work();
return ;
}
[POJ 3728]The merchant的更多相关文章
- [最近公共祖先] POJ 3728 The merchant
The merchant Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 4556 Accepted: 1576 Desc ...
- poj 3728 The merchant(LCA)
Description There are N cities in a country, and there is one and only one simple path between each ...
- POJ 3728 The merchant(并查集+DFS)
[题目链接] http://poj.org/problem?id=3728 [题目大意] 给出一棵树,每个点上都可以交易货物,现在给出某货物在不同点的价格, 问从u到v的路程中,只允许做一次买入和一次 ...
- poj——3728 The merchant
The merchant Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 5055 Accepted: 1740 Desc ...
- POJ 3728 The merchant(LCA+DP)
The merchant Time Limit : 6000/3000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) Total ...
- poj 3728 The merchant 倍增lca求dp
题目: zdf给出的题目翻译: 从前有一个富饶的国度,在这里人们可以进行自由的交易.这个国度形成一个n个点的无向图,每个点表示一个城市,并且有一个权值w[i],表示这个城市出售或收购这个权值的物品.又 ...
- POJ 3728 The merchant (树形DP+LCA)
题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...
- POJ——T 3728 The merchant
http://poj.org/problem?id=3728 Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 5068 A ...
- POJ - 3728:The merchant (Tarjan 带权并查集)
题意:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. 思路 ...
随机推荐
- C#/AutoCAD 2018/ObjectArx/二次开发再说实体(六)
这些函数对大家很有用,如果想获取详细源代码请加云幽学院yunyou.ke.qq.com报名免费课程,如果想学习更系统.更全面的知识请报名收费课程,有大量开发案例共享. 1.获取模型空间中所有实体 #r ...
- Ditto在教学上的应用
Ditto在教学上的应用 我喜欢iOS和macOS生态的一个原因是,你在iphone上看到一段好文字,复制一下,到macbook中粘贴一下就可以了,这体验太爽了. 大家可能相信大家都听过这样一则笑话: ...
- Alpha冲刺Day9
Alpha冲刺Day9 一:站立式会议 今日安排: 经过为期5天的冲刺,基本完成企业人员模块的开发.因第三方机构与企业存在委托的关系.第三方人员对于风险的自查.风险列表的展示以及自查风险的统计展示(包 ...
- ArcGIS地图打印那些事
记录了通过ArcGIS的PringTask进行地图打印,以及借助html2canvas实现屏幕截图的方法.两个方法各有适用的情景.过程中涉及的相关资源和问题给出链接,自行查看. 1.需求背景 地图打印 ...
- 第二章 初识JSP
第二章 初识JSP 一.JSP简述 1.是JSP JSP是指在HTML中嵌入Java脚本语言.全称(Java Server Pages) 当用户通过浏览器访问Web应用时,使用JSP容器对请求的J ...
- 3-51单片机WIFI学习(开发板8266底层源码介绍)
上一篇链接 http://www.cnblogs.com/yangfengwu/p/8743502.html 直接上源码:注意源码有两部分,第一部分是一开始的时候写在模块内部的,另一部分是存在手机内 ...
- JS的if和switch
var aa=parseInt(prompt("请输入你的年龄")); //定义输入 if(aa<18){ //输出小于18,返回值少年 alert("少年&quo ...
- jprofiler配置
cataline.sh JAVA_OPTS="$JAVA_OPTS -agentlib:jprofilerti=port=8849"JAVA_OPTS="$JAVA_OP ...
- jenkins创建multibranch pipeline
参考以下文章进行实践: https://jenkins.io/doc/pipeline/tour/hello-world/#what-is-a-jenkins-pipeline (看见一个介绍的还不错 ...
- jq中的表单验证插件------jquery.validate
今天我们来说一下表单验证,有人说我们在进行表单验证的时候使用正则来验证是非常麻烦的,现在我来给大家介绍一下表单验证的插件:jquery.validate.min.js 它是与jquery一起结合用来使 ...