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;
    }
    



  • 相关阅读:
    html5 保存图片到服务器本地
    html5 canvas分层
    webstorm配置scss自动编译路径
    微信开发测试号配置
    html5手机网站需要加的那些meta/link标签,html5 meta全解
    css去掉iPhone、iPad默认按钮样式
    如何激活webstorm 11
    min-height在安卓下不起作用
    基于字符串模式的路由路径的一些示例。
    nodeJS搭建本地服务器
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9643402.html
Copyright © 2011-2022 走看看