一天,你们wyh学长和你们zhl学长玩一个游戏,这个游戏规则是这样的
给你n个城市,保证这n个城市之间都只有一条道路可以到达。
有一件物品,在所有城市中都是一样的,但是由于各个城市的经济发展不同,导致每个城市对于这件物品销售的价格不同。
游戏一共进行Q轮。
每轮给你2个点s和t,其中s代表起点,t代表终点。
对于每一个城市都可以选择买这个物品,如果手里有这个物品的话,也可以选择卖掉这个物品,对于同一个城市来说,买和卖的价格是一样的,每一个城市只能买一件物品
现在,你们wyh学长和zhl学长都需要找到一个方案,使得从起点走到终点的时候盈利最多,请你帮助帮助他们吧。
(题意巨坑, 要求一条路径只能买卖一次。。。)
思路:离线, 利用tarjan离线求lca 的思想, 利用并查集维护链上的最大值, 最小值, 上升时的最大差值, 下降时的最大差值, 对于一个s, t的询问
当dfs回溯到 lca = lca(s, t) 的时候s 到 lca 和 t 到 lca 的最大值, 最小值, 上升时的最大差值, 下降时的最大差值都已经知道啦,然后就能更新答案啦。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define fi first 4 #define se second 5 #define mk make_pair 6 #define pii pair<int,int> 7 using namespace std; 8 9 const int N = 1e5 + 7; 10 const int M = 100 + 7; 11 const int inf = 0x3f3f3f3f; 12 const LL INF = 0x3f3f3f3f3f3f3f3f; 13 const int mod = 1e9 + 7; 14 15 int n, m, mn[N], mx[N], up[N], down[N], ans[N], fa[N]; 16 17 bool vis[N]; 18 19 struct Qus { 20 int s, t, id; 21 }; 22 23 vector<Qus> qus[N]; 24 vector<pii> Q[N]; 25 vector<int> edge[N]; 26 27 28 int Find(int x) { 29 if(fa[x] == x) 30 return x; 31 int root = Find(fa[x]); 32 up[x] = max(max(up[x], up[fa[x]]), mx[fa[x]] - mn[x]); 33 down[x] = max(max(down[x], down[fa[x]]), mx[x] - mn[fa[x]]); 34 mn[x] = min(mn[x], mn[fa[x]]); 35 mx[x] = max(mx[x], mx[fa[x]]); 36 return fa[x] = root; 37 } 38 39 void dfs(int u) { 40 vis[u] = true; 41 for(pii v : Q[u]) { 42 if(vis[v.fi]) { 43 int lca = Find(v.fi); 44 if(v.se > 0) { 45 qus[lca].push_back({u, v.fi, v.se}); 46 } else { 47 qus[lca].push_back({v.fi, u, -v.se}); 48 } 49 } 50 } 51 52 for(int v : edge[u]) { 53 if(!vis[v]) { 54 dfs(v); 55 fa[v] = u; 56 } 57 } 58 59 for(Qus now : qus[u]) { 60 int x = now.s, y = now.t, id = now.id; 61 Find(x); Find(y); 62 ans[id] = max(mx[y] - mn[x], max(up[x], down[y])); 63 } 64 } 65 int main() { 66 67 scanf("%d", &n); 68 69 for(int i = 1; i <= n; i++) { 70 int w; scanf("%d", &w); 71 mn[i] = mx[i] = w; 72 fa[i] = i; 73 } 74 75 for(int i = 1; i < n; i++) { 76 int u, v; scanf("%d%d", &u, &v); 77 edge[u].push_back(v); 78 edge[v].push_back(u); 79 } 80 81 scanf("%d", &m); 82 for(int i = 1; i <= m; i++) { 83 int s, t; scanf("%d%d", &s, &t); 84 Q[s].push_back(mk(t, i)); 85 Q[t].push_back(mk(s, -i)); 86 } 87 88 dfs(1); 89 90 for(int i = 1; i <= m; i++) { 91 printf("%d ", ans[i]); 92 } 93 return 0; 94 } 95 96 /* 97 */