POJ 3728 The merchant (LCA)

f[i][j] : i 的第 2^j 个祖先


Max[i][j] : 从 i 到 f[i][j] 的最高价格


Min[i][j] : 从 i 到 f[i][j] 的最低价格


up[i][j] : 从 i 往上走到 f[i][j] 的最大收益


down[i][j] : 从 f[i][j] 往下走到 i 的最大收益


然后用DP的方法,分类讨论即可。

The merchant
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 3379   Accepted: 1125

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

Source

POJ Monthly Contest – 2009.04.05, GaoYihan

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define prt(k) cout<<#k" = "<<k<<endl;
typedef long long ll;
const int N = 100005;
const int inf = 0x3f3f3f3f;
int val[N];
int head[N], mm;
int n;
struct Edge
{
    int to, next;
}e[N << 1];
int dep[N], f[N][22];
int Max[N][22], Min[N][22];
int up[N][22], down[N][22];
void init()
{
    mm = 0;
    memset(head, -1, sizeof head);
    dep[1] = -1;
    memset(Max, 0, sizeof Max);
    memset(Min, 63, sizeof Min);
    val[0] = val[1];
}
void add(int u, int v)
{
    e[mm] = (Edge) {v, head[u]};
    head[u] = mm++;
}
void dfs(int u, int fa)
{
    dep[u] = dep[fa] + 1;
    f[u][0] = fa;
    up[u][0] = max(val[fa] - val[u], 0);
    down[u][0] = max(val[u] - val[fa], 0);
    Max[u][0] = max(val[u], val[fa]);
    Min[u][0] = min(val[u], val[fa]);
    for (int i=head[u];~i;i=e[i].next)
    {
        int v = e[i].to;
        if (v == fa) continue;
        dfs(v, u);
    }
}
int maxh;
void gao()
{
    int j;
    for (j=1;(1<<j)<n;j++) {
         for (int i=1;i<=n;i++) {
            int t = f[i][j-1];
            f[i][j] = f[t][j-1];
            Max[i][j] = max(Max[i][j-1], Max[t][j-1]);
            Min[i][j] = min(Min[i][j-1], Min[t][j-1]);
            up[i][j] = max(max(up[i][j-1], up[t][j-1]),
                           Max[t][j-1] - Min[i][j-1]);
            down[i][j] = max(max(down[i][j-1], down[t][j-1]),
                             Max[i][j-1] - Min[t][j-1]);
         }
    }
    maxh = j - 1;
}
int swim(int x, int k)
{
    for (int i=maxh;i>=0;i--) {
        if (k >> i & 1) {
            x = f[x][i];
        }
    }
    return x;
}
#include <vector>
int UP(int x, int k, int &mi)
/// x 向上走 k 步能够得到的最大收益以及经过城市的最小价格
{
    mi = inf;
    int ret = 0;
    int tmp = inf;
    for (int i=maxh;i>=0;i--) {
        if (k >> i & 1) {
            mi = min(mi, Min[x][i]);
            ret = max(ret, up[x][i]);
            ret = max(ret, Max[x][i] - tmp);
            tmp = min(tmp, Min[x][i]);
            x = f[x][i];
        }
    }
    return ret;
}
int DOWN(int x, int k, int &ma)
/// 从 x 的第 k 个祖先向下走到 x 能够得到的最大收益以及经过城市的最大价格
{
    ma = 0;
    int ret = 0;
    int tmp = 0;
    for (int i=maxh;i>=0;i--) {
        if (k >> i & 1) {
            ma = max(ma, Max[x][i]);
            ret = max(ret, down[x][i]);
            ret = max(ret, tmp - Min[x][i]);
            tmp = max(tmp, Max[x][i]);
            x = f[x][i];
        }
    }
    return ret;
}
int LCA(int x, int y)
{
    if (dep[x] > dep[y]) swap(x, y);
    y = swim(y, dep[y] - dep[x]);
    if (x == y) return x;
    for (int i=maxh;i>=0;i--) {
        if (f[x][i] != f[y][i] ) {
            x = f[x][i], y = f[y][i];
        }
    }
    return f[x][0];
}
int main()
{
    while (cin >> n) {
        for (int i=1;i<=n;i++) scanf("%d", val+i);
        init();
        for (int i=0;i<n-1;i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v); add(v, u);
        }
        dfs(1, 1);
        gao();
        int Q; cin >> Q;
        while (Q--) {
            int x, y;
            scanf("%d%d", &x, &y);
            int lca = LCA(x, y);
            int ma, mi;
            int u = UP(x, dep[x] - dep[lca], mi);
            int d = DOWN(y, dep[y] - dep[lca], ma);
            int ans = max(max(u, d), ma - mi);
            printf("%d\n", ans);
        }
    }
    return 0;
}


你可能感兴趣的:(dp,tree,poj,DFS,LCA)