hdoj 5052 Yaoge’s maximum profit 【树链剖分】

来源:互联网 发布:js实现bind 编辑:程序博客网 时间:2024/05/16 06:24

Yaoge’s maximum profit

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 870    Accepted Submission(s): 244


Problem Description
Yaoge likes to eat chicken chops late at night. Yaoge has eaten too many chicken chops, so that Yaoge knows the pattern in the world of chicken chops. There are N cities in the world numbered from 1 to N . There are some roads between some cities, and there is one and only one simple path between each pair of cities, i.e. the cities are connected like a tree. When Yaoge moves along a path, Yaoge can choose one city to buy ONE chicken chop and sell it in a city after the city Yaoge buy it. So Yaoge can get profit if Yaoge sell the chicken chop with higher price. Yaoge is famous in the world. AFTER Yaoge has completed one travel, the price of the chicken chop in each city on that travel path will be increased by V .
 

Input
The first line contains an integer T (0 < T ≤ 10), the number of test cases you need to solve. For each test case, the first line contains an integer N (0 < N ≤ 50000), the number of cities. For each of the next N lines, the i-th line contains an integer Wi(0 < Wi ≤ 10000), the price of the chicken chop in city i. Each of the next N - 1 lines contains two integers X Y (1 ≤ X, Y ≤ N ), describing a road between city X and city Y . The next line contains an integer Q(0 ≤ Q ≤ 50000), the number of queries. Each of the next Q lines contains three integer X Y V(1 ≤ X, Y ≤ N ; 0 < V ≤ 10000), meaning that Yaoge moves along the path from city X to city Y , and the price of the chicken chop in each city on the path will be increased by V AFTER Yaoge has completed this travel.
 

Output
For each query, output the maximum profit Yaoge can get. If no positive profit can be earned, output 0 instead.
 

Sample Input
15123451 22 33 44 551 5 15 1 11 1 25 1 11 2 1
 

Sample Output
40010
 

SB,线段树区间更新,写成单点更新了。T成狗了。 o(╯□╰)o

题意:给定n个鸡排店以及每个店鸡排的单价,有n-1条路连通所有的店。现在有Q次查询,x y z表示查询从x->y路径上可以获取的最大利润,你需要在第i个店买一个鸡排,在第j个店卖出,要求x -> i - > ... -> j -> y,其中i和j是可以相等的。走过x -> y的路径后,该路径上所有店的单价会升高z。


思路:在链上线段树维护区间最大值Max 最小值Min 往返最大利润best[2]。在沿着链找最大利润有点坑,考虑的情况有点多。


AC代码:


#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <set>#include <vector>#include <string>#define INF 0x3f3f3f3f#define eps 1e-8#define MAXN (50000+10)#define MAXM (300000+10)#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%.2lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while((a)--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 1000000007#define LL long long#define lson o<<1, l, mid#define rson o<<1|1, mid+1, r#define ll o<<1#define rr o<<1|1#define PI acos(-1.0)#pragma comment(linker, "/STACK:102400000,102400000")#define fi first#define se secondusing namespace std;struct Tree{    int l, r, Min, Max, lazy, len, best[2];};Tree tree[MAXN<<2];void PushUp(int o){    tree[o].Max = max(tree[ll].Max, tree[rr].Max);    tree[o].Min = min(tree[ll].Min, tree[rr].Min);    tree[o].best[0] = max(tree[ll].best[0], tree[rr].best[0]);    tree[o].best[0] = max(tree[o].best[0], tree[rr].Max - tree[ll].Min);    tree[o].best[1] = max(tree[ll].best[1], tree[rr].best[1]);    tree[o].best[1] = max(tree[o].best[1], tree[ll].Max - tree[rr].Min);}void PushDown(int o){    if(tree[o].lazy)    {        tree[ll].lazy += tree[o].lazy;        tree[rr].lazy += tree[o].lazy;        tree[ll].Max += tree[o].lazy;        tree[ll].Min += tree[o].lazy;        tree[rr].Min += tree[o].lazy;        tree[rr].Max += tree[o].lazy;        tree[o].lazy = 0;    }}int a[MAXN], pedge[MAXN];void Build(int o, int l, int r){    tree[o].l = l; tree[o].r = r;    tree[o].lazy = tree[o].best[0] = tree[o].best[1] = 0;    tree[o].len = r - l + 1;    if(l == r)    {        tree[o].Min = tree[o].Max = a[pedge[l]];        return ;    }    int mid = (l + r) >> 1;    Build(lson); Build(rson);    PushUp(o);}void Update(int o, int L, int R, int v){    if(tree[o].l == L && tree[o].r == R)    {        tree[o].lazy += v;        tree[o].Min += v;        tree[o].Max += v;        return ;    }    PushDown(o);    int mid = (tree[o].l + tree[o].r) >> 1;    if(R <= mid) Update(ll, L, R, v);    else if(L > mid) Update(rr, L, R, v);    else {Update(ll, L, mid, v); Update(rr, mid+1, R, v);}    PushUp(o);}int Query(int o, int L, int R, int &Min, int &Max, int op){    if(tree[o].l == L && tree[o].r == R)    {        Min = tree[o].Min; Max = tree[o].Max;        return tree[o].best[op];    }    PushDown(o);    int mid = (tree[o].l + tree[o].r) >> 1;    if(R <= mid) return Query(ll, L, R, Min, Max, op);    else if(L > mid) return Query(rr, L, R, Min, Max, op);    else    {        int lMin, lMax, rMin, rMax;        int ans = max(Query(ll, L, mid, lMin, lMax, op), Query(rr, mid+1, R, rMin, rMax, op));        Min = min(lMin, rMin); Max = max(lMax, rMax);        if(op == 0) ans = max(ans, rMax - lMin);        else ans = max(ans, lMax - rMin);        return ans;    }}struct Edge{    int to, next;};Edge edge[MAXN<<1];int head[MAXN], edgenum;void init(){    edgenum = 0; CLR(head, -1);}void addEdge(int u, int v){    edge[edgenum].to = v;    edge[edgenum].next = head[u];    head[u] = edgenum++;}int son[MAXN], num[MAXN];int top[MAXN], pos[MAXN], id;int dep[MAXN], pre[MAXN];void DFS1(int u, int fa, int d){    dep[u] = d; pre[u] = fa; num[u] = 1; son[u] = -1;    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].to;        if(v == fa) continue;        DFS1(v, u, d+1);        num[u] += num[v];        if(son[u] == -1 || num[son[u]] < num[v])            son[u] = v;    }}void DFS2(int u, int T){    top[u] = T; pos[u] = ++id; pedge[id] = u;    if(son[u] == -1) return ;    DFS2(son[u], T);    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].to;        if(v == pre[u] || v == son[u]) continue;        DFS2(v, v);    }}int Get(int u, int v){    int f1 = top[u], f2 = top[v];    int ans = 0, lMin = INF, rMin = INF, lMax = 0, rMax = 0;    int nowMax, nowMin;    while(f1 != f2)    {        if(dep[f1] < dep[f2])        {            ans = max(ans, Query(1, pos[f2], pos[v], nowMin, nowMax, 0));            ans = max(ans, rMax - nowMin);            rMax = max(rMax, nowMax); rMin = min(rMin, nowMin);            v = pre[f2], f2 = top[v];            //Update(1, pos[f2], pos[v], z);        }        else        {            ans = max(ans, Query(1, pos[f1], pos[u], nowMin, nowMax, 1));            ans = max(ans, nowMax - lMin);            lMax = max(lMax, nowMax); lMin = min(lMin, nowMin);            u = pre[f1], f1 = top[u];            //Update(1, pos[f1], pos[u], z);        }    }    if(dep[u] < dep[v])    {        ans = max(ans, Query(1, pos[u], pos[v], nowMin, nowMax, 0));        //Update(1, pos[u], pos[v], z);    }    else    {        ans = max(ans, Query(1, pos[v], pos[u], nowMin, nowMax, 1));        //Update(1, pos[v], pos[u], z);    }    ans = max(ans, rMax - nowMin);    ans = max(ans, nowMax - lMin);    ans = max(ans, rMax - lMin);    return ans;}void Change(int u, int v, int z){    int f1 = top[u], f2 = top[v];    while(f1 != f2)    {        if(dep[f1] < dep[f2])        {            swap(u, v);            swap(f1, f2);        }        Update(1, pos[f1], pos[u], z);        u = pre[f1], f1 = top[u];    }    if(dep[u] > dep[v]) swap(u, v);    Update(1, pos[u], pos[v], z);}int main(){    int t; Ri(t);    W(t)    {        int n; Ri(n); init();        for(int i = 1; i <= n; i++) Ri(a[i]);        for(int i = 1; i <= n-1; i++)        {            int s, e; Ri(s); Ri(e);            addEdge(s, e);            addEdge(e, s);        }        DFS1(1, -1, 1); id = 0; DFS2(1, 1); Build(1, 1, id);        int Q; Ri(Q);        while(Q--)        {            int x, y, z;            Ri(x); Ri(y); Ri(z);            Pi(Get(x, y));            Change(x, y, z);        }    }    return 0;}



0 0
原创粉丝点击