[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,且只能购买并出售一次商品,问最多可以产生多大的利润. 思路 ...
随机推荐
- 想不到的:js中加号操作符
研究js加号操作符的时候,无意中试验了一个 console.log({} + "str");//NaN 发现结果居然是NaN,这让我百思不得其解. 我查阅资料,js高级编程里是这样 ...
- 项目Beta冲刺Day7
项目进展 李明皇 今天解决的进度 部分数据传递和使用逻辑测试 林翔 今天解决的进度 服务器端查看个人发布的action,修改已发布消息状态的action,仍在尝试使用第三方云存储功能保存图片 孙敏铭 ...
- 服务器数据恢复方法_存储raid硬盘离线数据恢复案例
[故障描述]某法院的一台HP-P4500的存储系统,底层是12块1TB的硬盘组的RAID.其中每6个1TB的盘一组,第一组的前面一部分组了一个RAID0+1,是存放HP-P4500嵌入式系统,接着组了 ...
- SQL常用语句,随时用随时更新
更多详细说明文档查询 http://www.postgres.cn/docs/9.5/infoschema-columns.html 1.1通过表名查询表的属性 SELECT * FROM sys.s ...
- surging教学视频资源汇总
surging是什么 surging 是一个分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper.Consul作为surging服务的注册中心,集成了哈希,随机,轮询.压力最小优先作 ...
- 【转】Python处理wave文件
#本文PDF版下载 Python解析Wav文件并绘制波形的方法 #本文代码下载 Wav波形绘图代码 #本文实例音频文件night.wav下载 音频文件下载 (石进-夜的钢琴曲) 前言 在现在繁忙的生活 ...
- 用anaconda安装最新的TensorFlow版本
Google发布了TensorFlow1.4正式版 在anaconad搜索依旧是1.2的版本,通过一番查阅,找到了方法 1,打开anaconda-prompt 2,激活你要安装的环境 activate ...
- 基于RNN的音频降噪算法 (附完整C代码)
前几天无意间看到一个项目rnnoise. 项目地址: https://github.com/xiph/rnnoise 基于RNN的音频降噪算法. 采用的是 GRU/LSTM 模型. 阅读下训练代码,可 ...
- 使用HTML5视频事件示例
<!DOCTYPE html > <html > <head> <title>Video events example</title> &l ...
- Linux CentOS7.0 (02)修改主机名和ip地址
一.主机名修改 1.查看命令 在CentOS中,有三种定义的主机名:静态的(static),瞬态的(transient),和灵活的(pretty). "静态"主机名也称为内核主机名 ...