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 ≤ NwiQ ≤ 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的更多相关文章

  1. [最近公共祖先] POJ 3728 The merchant

    The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 4556   Accepted: 1576 Desc ...

  2. poj 3728 The merchant(LCA)

    Description There are N cities in a country, and there is one and only one simple path between each ...

  3. POJ 3728 The merchant(并查集+DFS)

    [题目链接] http://poj.org/problem?id=3728 [题目大意] 给出一棵树,每个点上都可以交易货物,现在给出某货物在不同点的价格, 问从u到v的路程中,只允许做一次买入和一次 ...

  4. poj——3728 The merchant

    The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5055   Accepted: 1740 Desc ...

  5. POJ 3728 The merchant(LCA+DP)

    The merchant Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total ...

  6. poj 3728 The merchant 倍增lca求dp

    题目: zdf给出的题目翻译: 从前有一个富饶的国度,在这里人们可以进行自由的交易.这个国度形成一个n个点的无向图,每个点表示一个城市,并且有一个权值w[i],表示这个城市出售或收购这个权值的物品.又 ...

  7. POJ 3728 The merchant (树形DP+LCA)

    题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...

  8. POJ——T 3728 The merchant

    http://poj.org/problem?id=3728 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5068   A ...

  9. POJ - 3728:The merchant (Tarjan 带权并查集)

    题意:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. 思路 ...

随机推荐

  1. 网络1712--c语言一二维数组作业总结

    1.成绩摆前头 1.1基本要求(1分) 按时交 - 有分 未交 - 0分 迟交一周以上 - 倒扣本次作业分数 抄袭 - 0分 泛泛而谈(最多七分) 1.2评分要点 PTA作业总结(4分) 同学代码互评 ...

  2. 和为S的连续正数序列——牛客网(剑指offer)

    题目描述 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久,他 ...

  3. 20145237 实验二 “Java面向对象程序设计”

    20145237 实验二 “Java面向对象程序设计” 实验内容 • 理解并掌握面向对象三要素:封装.继承.多态 • 初步掌握UML建模 • 熟悉S.O.L.I.D原则 • 使用TDD设计实现复数类 ...

  4. git中级技能

    中级技能(上)               一.实验说明 从本节开始,我们会介绍一些中级和高级的用法,这些用法很少用到,前面三节的内容已经满足了日常工作需要,从本节开始的内容可以简单了解,需要的时候再 ...

  5. js判断flash文件是否加载完毕

    轮询判断加载进度 img的加载完成有onload方法,一直不知道该怎么判断swf文件是否加载完毕了? 在应用中使用了轮询判断加载进度值PercentLoaded是否达到100,经测试,可以达到效果. ...

  6. 关于python爬虫经常要用到的一些Re.正则表达式

    转载:https://blog.csdn.net/skyeyesxy/article/details/50837984 1.正则表达式的常用符号与方法 常用符号:点号,星号,问号与括号(小括号) (. ...

  7. CentOS 7 PHP-redis扩展安装,浏览器不显示数据及redis无法储存数据常见问题解决办法

    首先使用php -m 可以查看到自己安装了那些扩展. 1.使用wget下载redis压缩包 wget https://github.com/phpredis/phpredis/archive/deve ...

  8. JWT(JSON Web Token) 多网站的单点登录,放弃session

    多个网站之间的登录信息共享, 一种解决方案是基于cookie - session的登录认证方式,这种方式跨域比较复杂. 另一种替代方案是采用基于算法的认证方式, JWT(json web token) ...

  9. jprofiler配置

    cataline.sh JAVA_OPTS="$JAVA_OPTS -agentlib:jprofilerti=port=8849"JAVA_OPTS="$JAVA_OP ...

  10. express学习(三)—— cookie和session

    express学习(三)-- cookie和session cookie存在浏览器中,最大只能保存4K数据,不安全 session存在服务器中,不能独立(先读取cookie再读取session),较安 ...