poj 3728 The merchant

来源:互联网 发布:brpc 知乎 编辑:程序博客网 时间:2024/05/16 05:08
    记 i 的第 2^j 个祖先为k,ma[j][i] ,mi[j][i] 分别为 i 到 k 的 最大最小值 up[j][i] 为 从 i 走到 k 的最大获利 ,down[j][i], 为 从k走到i的最大获利,  对于某一段up[j][i], 记i 的 第 2^(j-1)  个祖先为 v  则 up[j][i] =max(max( up[j-1][v],up[j-1][i]),ma[j-1][v]-mi[j-1][i]));当然,当j 逐渐变大以后,up[j][i] =max(max( up[j-1][v],up[j-1][i]),ma[j-1][v]-mi[j-1][i])) 中的 m[j-1][i]变为已经过路径上的最小值。

#include <utility>#include <algorithm>#include <string>#include <cstring>#include <cstdio>#include <iostream>#include <iomanip>#include <set>#include <vector>#include <cmath>#include <queue>#include <bitset>#include <map>#include <iterator>using namespace std;#define clr(a,v) memset(a,v,sizeof(a))#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int INF = 100000000;const int maxn = 51111;const int POW = 18;const double pi = acos(-1.0);const double eps = 1e-8;const int mod = 777777777;typedef long long LL;typedef unsigned long long ULL;typedef pair<int, int> pii;typedef vector<int> VI;typedef vector<VI> VVI;typedef vector<VVI> VVVI;int w[maxn];struct node {int v, next;node() {}node(int v, int next) :v(v), next(next) {}} edge[maxn << 2];int head[maxn], E, n;int ma[POW][maxn], mi[POW][maxn], up[POW][maxn], down[POW][maxn];int p[POW][maxn], d[maxn];bool vis[maxn];void init() {clr(head, -1);E = 0;}void add_edge(int u, int v) {edge[E] = node(v, head[u]);head[u] = E++;edge[E] = node(u, head[v]);head[v] = E++;}void dfs(int u, int pre) {vis[u] = true;int i, v;p[0][u] = pre;mi[0][u] = min(w[pre], w[u]);ma[0][u] = max(w[pre], w[u]);up[0][u] = w[pre] - w[u];down[0][u] = w[u] - w[pre];for (i = 1; i < POW; ++i) {v = p[i - 1][u];p[i][u] = p[i - 1][v];mi[i][u] = min(mi[i-1][u], mi[i - 1][v]);ma[i][u] = max(ma[i-1][u], ma[i - 1][v]);up[i][u] = max(up[i - 1][u], up[i - 1][v]);up[i][u] = max(up[i][u], ma[i - 1][v] - mi[i - 1][u]);down[i][u] = max(down[i - 1][u], down[i - 1][v]);down[i][u] = max(down[i][u], ma[i - 1][u] - mi[i - 1][v]);}for (i = head[u]; ~i; i = edge[i].next) {v = edge[i].v;if (vis[v])continue;d[v] = d[u] + 1;dfs(v, u);}}int find(int u, int k) {for (int i = 0; i < POW; ++i) {if ((k >> i) & 1)u = p[i][u];}return u;}int query(int a, int b) {int i;if (d[a] > d[b])swap(a, b);if (d[a] < d[b])b = find(b, d[b] - d[a]);if (a ^ b) {for (i = POW - 1; i >= 0; --i) {if (p[i][a] ^ p[i][b])a = p[i][a], b = p[i][b];}a = p[0][a];}return a;}template<typename T>inline const T& getmin(const T& a, const T& b) {return a < b ? a : b;}template<typename T>inline T const& getmax(const T& a, const T& b) {return a > b ? a : b;}template<class T>void get_val(int u, int v, int &res, int dp[POW][maxn], const T &f) {int i, delta = d[u] - d[v];res = w[u];for (i = 0; i < POW; ++i) {if ((delta >> i) & 1) {res = f(res, dp[i][u]);u = p[i][u];}}}int DP_UP(int u, int v) {int i, delta = (d[u] - d[v]);int res = w[v] - w[u], tmp = INF;for (i = 0; i < POW; ++i) {if ((delta >> i) & 1) {res = max(res, up[i][u]);res = max(res, ma[i][u] - tmp);tmp = min(tmp, mi[i][u]);u = p[i][u];}}return res;}int DP_DOWN(int u, int v) {int i, delta = (d[u] - d[v]);int res = w[u] - w[v], tmp = -INF;for (i = 0; i < POW; ++i) {if ((delta >> i) & 1) {res = max(res, down[i][u]);res = max(res, tmp - mi[i][u]);tmp = max(tmp, ma[i][u]);u = p[i][u];}}return res;}int solve(int u, int v) {int c = query(u, v);int maxv, minv;get_val(u, c, minv, mi, getmin<int>);get_val(v, c, maxv, ma, getmax<int>);int ans = max(DP_UP(u, c), DP_DOWN(v, c));ans = max(ans, maxv - minv);return ans;}int main() {ios::sync_with_stdio(false);int i, m, u, v;scanf("%d", &n);init();for (i = 1; i <= n; ++i)scanf("%d", w + i);for (i = 1; i < n; ++i) {scanf("%d%d", &u, &v);add_edge(u, v);}d[1] = 0;dfs(1, 1);scanf("%d", &m);while (m--) {scanf("%d%d", &u, &v);printf("%d\n", solve(u, v));}return 0;}


原创粉丝点击