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

倍增 LCA还是完全不会写.....

所以是看的题解

刚开始完全不能理解为什么这道题也能转换成LCA 找得到公共祖先然后呢 然后呢 然后呢

建的图相当于一个dfs树 路径是唯一的

找公共祖先t就相当于找到这条路径 公共祖先把这个路径分成了两半

最后(u, v)的答案有三种可能

1.u到t完成了买和卖

2.t到v完成了买和卖

3.在u到t某点买,t到v某点卖

因此现在需要一个up数组,up[i][j]维护i到i节点往上2^j的节点的最大差价

down数组,down[i][j]维护i到i节点往下2^j的节点的最大差价

Max数组, Max[i][j]维护i到i节点往上2^j的节点之间价格的最大值

Min数组,Min[i][j]维护i到i节点往上2^j的节点之间价格的最小值

parent数组,parent[i][0]存储每个节点的父亲,用dfs先预处理出来。用倍增的思想处理出parent[i][j]表示i往上2^j的节点

#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <stdio.h>
#include <queue>
#include <stack>
#define inf 0x3f3f3f3f
using namespace std; int n, q, ecnt;
const int maxn = 50005;
int Max[maxn][20], Min[maxn][20], up[maxn][20], down[maxn][20], parent[maxn][20];
vector <int> g[maxn];
int dep[maxn],val[maxn]; void dfs(int u, int fa)
{
for(int i = 0; i < g[u].size(); i++){
int v = g[u][i];
if(v == fa) continue;
dep[v] = dep[u] + 1;
parent[v][0] = u;
Max[v][0] = max(val[v], val[u]);
Min[v][0] = min(val[v], val[u]);
down[v][0] = max(0, val[v] - val[u]);
up[v][0] = max(0, val[u] - val[v]);
dfs(v, u);
}
} void init()
{
dep[1] = 1;
memset(parent, -1, sizeof(parent));
dfs(1, 0);
for(int j = 1; (1 << j) <= n; j++){
for(int i = 1; i <= n; i++){
if(~parent[i][j - 1]){
int k = parent[i][j - 1], a, b;
parent[i][j] = parent[k][j - 1];
Max[i][j] = max(Max[i][j - 1], Max[k][j - 1]);
Min[i][j] = min(Min[i][j - 1], Min[k][j - 1]);
a = max(0, Max[i][j - 1] - Min[k][j - 1]), b = max(down[i][j - 1], down[k][j - 1]);
down[i][j] = max(a, b);
a = max(0, Max[k][j - 1] - Min[i][j - 1]), b = max(up[i][j - 1], up[k][j - 1]);
up[i][j] = max(a,b);
}
}
}
} int LCA(int a, int b)
{
if(dep[a] < dep[b]) swap(a, b);
int i;
for(i = 0; (1 << i) <= dep[a]; i++);
i--;
for(int j = i; j >= 0; j--){
if(dep[a] - (1 << j) >= dep[b]){
a = parent[a][j];
}
}
if(a == b){
return a;
}
for(int j = i; j >= 0; j--){
if(parent[a][j] != -1 && parent[a][j] != parent[b][j]){
a = parent[a][j];
b = parent[b][j];
}
}
return parent[a][0];
} int query_down(int x, int k, int &max_val)
{
int ans = 0;
max_val = 0;
for(int i = 18; i >= 0; i--){
if(k & (1 << i)){
ans = max(ans, down[x][i]);
ans = max(ans, max_val - Min[x][i]);
max_val = max(max_val, Max[x][i]);
x = parent[x][i];
}
}
return ans;
} int query_up(int x, int k, int &min_val)
{
int ans = 0;
min_val = inf;
for(int i = 18; i >= 0; i--){
if(k & (1 << i)){
ans = max(ans, up[x][i]);
ans = max(ans, Max[x][i] - min_val);
min_val = min(min_val, Min[x][i]);
x = parent[x][i];
}
}
return ans;
} int main()
{
while(scanf("%d", &n) != EOF){
for(int i = 1; i <= n; i++){
scanf("%d", &val[i]);
}
for(int i = 1; i <= n; i++){
g[i].clear();
}
for(int i = 1; i < n; i++){
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
init();
scanf("%d", &q);
while(q--){
int u, v;
scanf("%d%d", &u, &v);
int t = LCA(u, v);
int min_val, max_val, a, b;
a = query_up(u, dep[u] - dep[t], min_val);
b = query_down(v, dep[v] - dep[t], max_val);
int ans = max(max(0, max_val - min_val), max(a, b));
cout<<ans<<endl;
}
}
return 0;
}

最新文章

  1. NoSql数据库初探-mongoDB读操作
  2. AppleDoc的安裝使用
  3. NSoperation用法详解及与GCD的比较
  4. 74HC595
  5. Swift - 类扩展(extension)
  6. JS日期时间加减实现
  7. 新型勒索软件Magniber正瞄准韩国、亚太地区开展攻击
  8. spring 中的设计模式
  9. PostgreSQL自学笔记:6 PostgreSQL函数
  10. TDD:什么是桩(stub)和模拟(mock)?
  11. [转] 理解Object.defineProperty的作用
  12. 在见证了1000多家公司的兴衰灭亡之后,YC创始合伙人总结了创业公司的6个不死法则(转)
  13. matchesSelector()方法
  14. 使用Log4j将程序日志实时写入Kafka(转)
  15. tomcat启动报错 java.lang.ClassNotFoundException: org.apache.jsp.index_jsp
  16. C基础 旋转数组查找题目
  17. Thunder7.2.13.3884 JayXon
  18. 【转+整理+答案】python315+道面试题
  19. Motion Detection Algorithms视频中运动检测算法源代码及演示代码
  20. [GO]匿名字段

热门文章

  1. 浏览器端Less
  2. Java中Volatile详解
  3. Linux服务器部署 Elasticsearch 成功,本机却访问不了
  4. 抓包工具Wireshark
  5. Visual Assist X 10.8.2042的Crack破解补丁. 2014.06.25 (General release.)
  6. SpringMVC由浅入深day01_9商品修改功能开发
  7. spray json, jackson 转到type时多key和少key的比较
  8. error C4996: Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct
  9. Extended VM Disk In VirtualBox or VMware (虚拟机磁盘扩容)
  10. 【数据分析】Superset 之一 准备