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



  • 相关阅读:
    土木工程材料0732
    07 具有无关项的逻辑函数及其化简
    06 逻辑函数化简法
    AD中板子挖孔开槽
    电容式触摸按键原理
    LTspice
    三相电
    7、简单电阻容元件模型的创建
    cadence17.4在笔记本下设置菜单显示不全的解决办法
    36. 二叉搜索树与双向链表
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9643402.html
Copyright © 2011-2022 走看看