POJ 3728 The merchant

来源:互联网 发布:solarman软件下载 编辑:程序博客网 时间:2024/05/01 07:05

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=34528#problem/L


#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int MAXN = 50010;const int POW  = 17;const int INF  = 0x3f3f3f3f;int val[MAXN], head[MAXN], cnt;int parent[MAXN][POW], dep[MAXN], mmin[MAXN][POW], mmax[MAXN][POW], up[MAXN][POW], down[MAXN][POW];/**parent[i][j]: 表示距离顶点i为2^j的祖先顶点的编号*up[i][j]: i->距离i为2^j的祖先顶点最大收益*down[i][j]: 距离i为2^j的祖先顶点->i顶点的最小收益*mmin[i][j]: i->距离i为2^j的祖先顶点的最小顶点的权值*mmax[i][j]: i->距离i为2^j的祖先顶点的最大顶点的权值*因此对于一组询问(u,v) ans = max(getmax_up(u, lca(u,v)), getmax_dwon(v, lca(u,v)), getmax(v, lca(u,v))-getmin(u, lca(u,v)))*/struct Edge{    int v, next;    Edge() {}    Edge(int t_v, int t_next) : v(t_v), next(t_next) {}}edge[2*MAXN];void addedge(int u, int v){    edge[cnt].v = v;    edge[cnt].next = head[u];    head[u] = cnt++;    edge[cnt].v = u;    edge[cnt].next = head[v];    head[v] = cnt++;}void Init(int n){    cnt = 0;    memset(head, -1, sizeof(head));    memset(dep,   0,   sizeof(dep));    memset(parent, 0, sizeof(parent));    for(int i = 1; i <= n; ++i)    {        for(int j = 0; j < POW; ++j)        {            mmin[i][j] = mmax[i][j] = up[i][j] = down[i][j] = 0;        }    }}void dfs(int u, int fa){    int i, j;    dep[u] = dep[fa] + 1;    for(i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].v;        if(v == fa) continue;        ////////////////////////////////////////////////////////////////////////////////        parent[v][0] = u;        mmin[v][0] = min(val[u], val[v]);        mmax[v][0] = max(val[u], val[v]);        up[v][0]   = val[u] - val[v];        down[v][0] = val[v] - val[u];        for(j = 1; (1<<j) <= dep[u] + 1; j++)        {            parent[v][j] = parent[parent[v][j-1]][j-1];            mmin[v][j]   = min(mmin[v][j-1], mmin[parent[v][j-1]][j-1]);            mmax[v][j]   = max(mmax[v][j-1], mmax[parent[v][j-1]][j-1]);            up[v][j] = max(up[v][j-1], up[parent[v][j-1]][j-1]);            up[v][j] = max(up[v][j],   mmax[parent[v][j-1]][j-1] - mmin[v][j-1]);            down[v][j] = max(down[v][j-1], down[parent[v][j-1]][j-1]);            down[v][j] = max(down[v][j],   mmax[v][j-1] - mmin[parent[v][j-1]][j-1]);        }        /////////////////////////////////////////////////////////////////////////////////        dfs(v, u);    }    return ;}int LCA(int u, int v){    int i;    if(dep[u] > dep[v]) u ^= v, v ^= u, u ^= v;    if(dep[u] < dep[v])    {        int del = dep[v] - dep[u];        for(i = 0; i < POW; i++)            if(del & (1<<i))                v = parent[v][i];    }    if(u != v)    {        for(i = POW - 1; i >= 0; i--)            if(parent[u][i] != parent[v][i])                u = parent[u][i], v = parent[v][i];        u = parent[u][0], v = parent[v][0];    }    return u;}int getmax_up(int u, int v){    int ans = 0, i, tmp = INF;    int del = dep[u] - dep[v];    for(i = POW-1; i >= 0; i--)    {        if(del & (1<<i))        {            ans = max(ans, up[u][i]);            ans = max(ans, mmax[u][i] - tmp);            tmp = min(tmp, mmin[u][i]);            u   = parent[u][i];        }    }    return ans;}int getmax_down(int u, int v){    int ans = 0, i, tmp = 0;    int del = dep[u] - dep[v];    for(i = POW-1; i >= 0; i--)    {        if(del & (1<<i))        {            ans = max(ans, down[u][i]);            ans = max(ans, tmp - mmin[u][i]);            tmp = max(tmp, mmax[u][i]);            u   = parent[u][i];        }    }    return ans;}int getmax(int u, int v){    int ans = 0, i;    int del = dep[u] - dep[v];    for(i = POW-1; i >= 0; i--)    {        if(del & (1<<i))        {            ans = max(ans, mmax[u][i]);            u   = parent[u][i];        }    }    return ans;}int getmin(int u, int v){    int ans = INF, i;    int del = dep[u] - dep[v];    for(i = POW-1; i >= 0; i--)    {        if(del & (1<<i))        {            ans = min(ans, mmin[u][i]);            u   = parent[u][i];        }    }    return ans;}void solve(int u, int v){    int lca = LCA(u, v);    int a, b, c, d;    a = getmax_up(u, lca);    b = getmax_down(v, lca);    c = getmin(u, lca);    d = getmax(v, lca);    printf("%d\n", max(max(a, b), d - c));}int main(){    //freopen("aa.in", "r", stdin);    int i, u, v, n, q;    scanf("%d", &n);    Init(n);    for(i = 1; i <= n; i++)        scanf("%d", &val[i]);    for(i = 1; i < n; i++)    {        scanf("%d %d", &u, &v);        addedge(u, v);    }    dfs(1, 0);    scanf("%d", &q);    for(i = 1; i <= q; i++)    {        scanf("%d %d", &u, &v);        solve(u, v);    }    return 0;}


原创粉丝点击