时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
一天,你们wyh学长和你们zhl学长玩一个游戏,这个游戏规则是这样的
给你n个城市,保证这n个城市之间都只有一条道路可以到达。
有一件物品,在所有城市中都是一样的,但是由于各个城市的经济发展不同,导致每个城市对于这件物品销售的价格不同。
游戏一共进行Q轮。
每轮给你2个点s和t,其中s代表起点,t代表终点。
对于每一个城市都可以选择买这个物品,如果手里有这个物品的话,也可以选择卖掉这个物品,对于同一个城市来说,买和卖的价格是一样的,每一个城市只能买一件物品
现在,你们wyh学长和zhl学长都需要找到一个方案,使得从起点走到终点的时候盈利最多,请你帮助帮助他们吧
输入描述:
每个测试文件中都只有一组测试数据
输入第一行一个整数n(1<=n<=50000),代表有n个城市
第二行输入n个数,代表每个城市对于这件物品的价格wi(1<=wi<=50000)
接下来有n-1行,每行2个数a和b,代表a到b之间有一条路
接下来输入一个数Q(1<=Q<=50000)
接下来Q行,每行2个数s和t
输出描述:
对于每组测试数据,输出对应答案,如果从起点到终点不能盈利的话,输出0
示例1
输入
复制
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
输出
复制
4
2
2
0
0
0
0
2
0
分析:
将城市看作一棵树,每两个城市之间有一个最近的公共祖先,那么获取的最大利益有三种可能
1.s-lca已经完成了买卖
2.lca-t已经完成了买卖
3.s-lca完成了买,lca-t完成了卖
所以up数字记录叶子节点到其祖先的最大买卖值,down数组记录祖先到叶子节点的最大买卖值,mx数组记录叶子节点到祖先节点的最大价格,mn数组记录叶子节点到祖先节点的最小价格。
因为要查询很多的情况,所以利用tarjan离线求得lca
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 7;
int n, m, mn[N], mx[N], up[N], down[N], ans[N], fa[N];
int vis[N];
struct node {
int s, t, id;
};
vector<node> g[N],q[N],e[N];
int Find(int x) {
if(fa[x] == x)
return x;
int root = Find(fa[x]);
up[x] = max(max(up[x], up[fa[x]]), mx[fa[x]] - mn[x]);
down[x] = max(max(down[x], down[fa[x]]), mx[x] - mn[fa[x]]);
mn[x] = min(mn[x], mn[fa[x]]);
mx[x] = max(mx[x], mx[fa[x]]);
return fa[x] = root;
}
void dfs(int u) {
vis[u] = 1;
for(int i=0;i<g[u].size();i++) {//遍历树
node v=g[u][i];
if(!vis[v.s]) {
dfs(v.s);
fa[v.s] = u;
}
}
for(int i=0;i<q[u].size();i++) {//找查询
node v=q[u][i];
if(vis[v.s]) {
int lca = Find(v.s);
if(v.id > 0) {
e[lca].push_back({u, v.s, v.id});
} else {
e[lca].push_back({v.s, u, -v.id});
}
}
}
for(int i=0;i<e[u].size();i++) {//计算获得的最大利益
node v=e[u][i];
int x = v.s, y = v.t, id = v.id;
Find(x); Find(y);
ans[id] = max(mx[y] - mn[x], max(up[x], down[y]));
}
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
int w; scanf("%d", &w);
mn[i] = mx[i] = w;
fa[i] = i;
}
int a,b;
node v;
for(int i = 1; i < n; i++) {
scanf("%d%d", &a, &b);
v.s=b;
g[a].push_back(v);
v.s=a;
g[b].push_back(v);
}
scanf("%d", &m);
for(int i = 1; i <= m; i++) {
int s, t; scanf("%d%d", &s, &t);
v.s=t,v.id=i;
q[s].push_back(v);
v.s=s,v.id=-i;
q[t].push_back(v);
}
dfs(1);
for(int i = 1; i <= m; i++) {
printf("%d\n", ans[i]);
}
return 0;
}