zoukankan      html  css  js  c++  java
  • poj3728The merchant 【倍增】【LCA】

    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

    倍增 LCA还是完全不会写.....

    所以是看的题解

    刚开始完全不能理解为什么这道题也能转换成LCA 找得到公共祖先然后呢 然后呢 然后呢

    建的图相当于一个dfs树 路径是唯一的

    找公共祖先t就相当于找到这条路径 公共祖先把这个路径分成了两半

    最后(u, v)的答案有三种可能

    1.u到t完成了买和卖

    2.t到v完成了买和卖

    3.在u到t某点买,t到v某点卖

    因此现在需要一个up数组,up[i][j]维护i到i节点往上2^j的节点的最大差价

    down数组,down[i][j]维护i到i节点往下2^j的节点的最大差价

    Max数组, Max[i][j]维护i到i节点往上2^j的节点之间价格的最大值

    Min数组,Min[i][j]维护i到i节点往上2^j的节点之间价格的最小值

    parent数组,parent[i][0]存储每个节点的父亲,用dfs先预处理出来。用倍增的思想处理出parent[i][j]表示i往上2^j的节点

    #include <iostream>
    #include <algorithm>
    #include <stdlib.h>
    #include <cstring>
    #include <vector>
    #include <map>
    #include <set>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #define inf 0x3f3f3f3f
    using namespace std;
    
    int n, q, ecnt;
    const int maxn = 50005;
    int Max[maxn][20], Min[maxn][20], up[maxn][20], down[maxn][20], parent[maxn][20];
    vector <int> g[maxn];
    int dep[maxn],val[maxn];
    
    void dfs(int u, int fa)
    {
        for(int i = 0; i < g[u].size(); i++){
            int v = g[u][i];
            if(v == fa) continue;
            dep[v] = dep[u] + 1;
            parent[v][0] = u;
            Max[v][0] = max(val[v], val[u]);
            Min[v][0] = min(val[v], val[u]);
            down[v][0] = max(0, val[v] - val[u]);
            up[v][0] = max(0, val[u] - val[v]);
            dfs(v, u);
        }
    }
    
    void init()
    {
        dep[1] = 1;
        memset(parent, -1, sizeof(parent));
        dfs(1, 0);
        for(int j = 1; (1 << j) <= n; j++){
            for(int i = 1; i <= n; i++){
                if(~parent[i][j - 1]){
                    int k = parent[i][j - 1], a, b;
                    parent[i][j] = parent[k][j - 1];
                    Max[i][j] = max(Max[i][j - 1], Max[k][j - 1]);
                    Min[i][j] = min(Min[i][j - 1], Min[k][j - 1]);
                    a = max(0, Max[i][j - 1] - Min[k][j - 1]), b = max(down[i][j - 1], down[k][j - 1]);
                    down[i][j] = max(a, b);
                    a = max(0, Max[k][j - 1] - Min[i][j - 1]), b = max(up[i][j - 1], up[k][j - 1]);
                    up[i][j] = max(a,b);
                }
            }
        }
    }
    
    int LCA(int a, int b)
    {
        if(dep[a] < dep[b]) swap(a, b);
        int i;
        for(i = 0; (1 << i) <= dep[a]; i++);
        i--;
        for(int j = i; j >= 0; j--){
            if(dep[a] - (1 << j) >= dep[b]){
                a = parent[a][j];
            }
        }
        if(a == b){
            return a;
        }
        for(int j = i; j >= 0; j--){
            if(parent[a][j] != -1 && parent[a][j] != parent[b][j]){
                a = parent[a][j];
                b = parent[b][j];
            }
        }
        return parent[a][0];
    }
    
    int query_down(int x, int k, int &max_val)
    {
        int ans = 0;
        max_val = 0;
        for(int i = 18; i >= 0; i--){
            if(k & (1 << i)){
                ans = max(ans, down[x][i]);
                ans = max(ans, max_val - Min[x][i]);
                max_val = max(max_val, Max[x][i]);
                x = parent[x][i];
            }
        }
        return ans;
    }
    
    int query_up(int x, int k, int &min_val)
    {
        int ans = 0;
        min_val = inf;
        for(int i = 18; i >= 0; i--){
            if(k & (1 << i)){
                ans = max(ans, up[x][i]);
                ans = max(ans, Max[x][i] - min_val);
                min_val = min(min_val, Min[x][i]);
                x = parent[x][i];
            }
        }
        return ans;
    }
    
    int main()
    {
        while(scanf("%d", &n) != EOF){
            for(int i = 1; i <= n; i++){
                scanf("%d", &val[i]);
            }
            for(int i = 1; i <= n; i++){
                g[i].clear();
            }
            for(int i = 1; i < n; i++){
                int u, v;
                scanf("%d%d", &u, &v);
                g[u].push_back(v);
                g[v].push_back(u);
            }
            init();
            scanf("%d", &q);
            while(q--){
                int u, v;
                scanf("%d%d", &u, &v);
                int t = LCA(u, v);
                int min_val, max_val, a, b;
                a = query_up(u, dep[u] - dep[t], min_val);
                b = query_down(v, dep[v] - dep[t], max_val);
                int ans = max(max(0, max_val - min_val), max(a, b));
                cout<<ans<<endl;
            }
        }
        return 0;
    }
    



  • 相关阅读:
    CSS实现水平居中的5种思路
    html5遵循的5个设计原则
    HTML5标签嵌套规则
    动画animation的三个应用(漂浮的白云、旋转的星球、正方体合成)
    深入理解CSS动画animation
    深入理解CSS径向渐变radial-gradient
    深入理解CSS线性渐变linear-gradient
    动态更新语句,时间精度丢失
    反射类的构造数
    在ASP.NET MVC中使用Grid.mvc
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9643402.html
Copyright © 2011-2022 走看看