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. C语言博客作业—函数嵌套调用

    一.实验作业 1.1 PTA题目:递归法对任意10个数据按降序排序 1.1.1设计思路 void sort(int a[],int n) { 定义整型循环变量i,中间变量temp,最小值min: 令m ...

  2. 判断mine类型

    var http = require("http"); var fs = require("fs"); var url = require("url& ...

  3. Hibernate之Hibernate的体系结构

    体系结构简图: 这是一张体系结构的简图,其中的hibernate.properties文件的作用相当于配置文件hibernate.cfg.xml XML Mapping对应的就是映射文件 XXXX.h ...

  4. bzoj千题计划165:bzoj5127: 数据校验

    http://www.lydsy.com/JudgeOnline/upload/201712/prob12.pdf 区间的任意一个子区间都满足值域连续 等价于 区间任意一个长为2的子区间都满足值域连续 ...

  5. python之路--day13---函数--三元表达式,递归,匿名函数,内置函数-----练习

    1.文件内容如下,标题为:姓名,性别,年纪,薪资 egon male 18 3000 alex male 38 30000 wupeiqi female 28 20000 yuanhao female ...

  6. 《网络》:设置三个密码:通过console口连接设备,进入特权模式,登录Telnet

    软件:Cisco Packet Tracer Instructor 软件下载链接在上一篇文章中. 内容:通过设置三个密码,熟悉采用Telnet方式配置交换机的方法. 细节说明:计算机的IP地址和交换机 ...

  7. Mego开发文档 - 快速开始

    Mego 快速开始 我们将创建一个简单的数据新增及查询来演示 Mego 的使用过程.演示中都是使用 Visual Studio 2017 作为开发工具,SQL Server 2012 作为数据库. 创 ...

  8. React Native学习(九)—— 使用Flexbox布局

    本文基于React Native 0.52 Demo上传到Git了,有需要可以看看,写了新内容会上传的.Git地址 https://github.com/gingerJY/React-Native-D ...

  9. hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(1)安装jdk

    一.文件准备 下载jdk-8u131-linux-x64.tar.gz 二.工具准备 2.1 Xshell 2.2 Xftp 三.操作步骤 3.1 解压文件: $ tar zxvf jdk-8u131 ...

  10. leetcode算法:Trim a Binar Search Tree

    Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so that a ...