hdu 5052 Yaoge’s maximum profit

Yaoge’s maximum profit

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

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

1
5
1
2
3
4
5
1 2
2 3
3 4
4 5
5
1 5 1
5 1 1
1 1 2
5 1 1
1 2 1

Sample Output

4
0
0
1
0

Source

2014 ACM/ICPC Asia Regional Shanghai Online

思路:lct or 树链分割

调了三天,终于过了,。。。不容易呀。。。

#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<map>
#include<ctime>
#include<bitset>
#define LL long long
#define INF 999999
#define mod 20140518
#define maxn 50010
using namespace std;

int head[maxn],next1[maxn*2],to[maxn*2] ;
int top1 ;
bool vi[maxn] ;
struct node
{
    int Max,Min;
    int add,lans,rans;
}tree[maxn*3],num[maxn];
int ql,qr,val ;
node vv ;
int max(int x,int y ){return x > y?x:y;}
int min(int x,int y ){return x < y?x:y;}

void Unit(int u,int v )
{
    next1[top1] = head[u] ;to[top1] = v ;
    head[u] = top1++;
}
void up(int o )
{
    tree[o].Max = max(tree[o<<1].Max,tree[o<<1|1].Max) ;
    tree[o].Min = min(tree[o<<1].Min,tree[o<<1|1].Min) ;
    tree[o].lans = max(tree[o<<1].lans,tree[o<<1|1].lans) ;
    tree[o].lans = max(tree[o].lans,tree[o<<1].Max-tree[o<<1|1].Min) ;
    tree[o].rans = max(tree[o<<1].rans,tree[o<<1|1].rans) ;
    tree[o].rans = max(tree[o].rans,tree[o<<1|1].Max-tree[o<<1].Min) ;
}
void Add(int o ,int add)
{
    tree[o].add += add ;
    tree[o].Max += add ;
    tree[o].Min += add ;
}
void down(int o )
{
    if(tree[o].add)
    {
       Add((o<<1),tree[o].add) ;
       Add((o<<1|1),tree[o].add) ;
       tree[o].add = 0;
    }
}
void insert(int L,int R,int o )
{
    tree[o].add=0;
    if(L==R)
    {
        tree[o] = num[L] ;
        return ;
    }
    int mid=(L+R)>>1 ;
    insert(L,mid,o<<1) ;
    insert(mid+1,R,o<<1|1) ;
    up(o) ;
}
void update(int L,int R,int o )
{
    if(ql <= L && qr >= R)
    {
        Add(o,val) ;
        return ;
    }
    down(o) ;
    int mid=(L+R)>>1 ;
    if(ql <= mid)update(L,mid,o<<1) ;
    if(qr > mid) update(mid+1,R,o<<1|1) ;
    up(o);
}
void find(int L,int R,int o,node &c )
{
    if(ql <= L && qr >= R)
    {
        c = tree[o] ;
        return ;
    }
    int mid=(L+R)>>1 ;
    down(o) ;
    if(ql > mid)
    {
       find(mid+1,R,o<<1|1,c) ;
       return ;
    }
    else if(qr <= mid)
    {
        find(L,mid,o<<1,c) ;
        return ;
    }
    node a ;
    find(L,mid,o<<1,a) ;
    node b ;
    find(mid+1,R,o<<1|1,b) ;
    c.Max = max(a.Max,b.Max) ;
    c.Min = min(a.Min,b.Min) ;
    c.lans = max(a.lans,max(a.Max-b.Min,b.lans)) ;
    c.rans = max(a.rans,max(b.Max-a.Min,b.rans)) ;
}
int w[maxn],fa[maxn],top[maxn],sz ;
int size1[maxn],son[maxn] ,dep[maxn];
void init()
{
    memset(w,0,sizeof(w));
    memset(size1,0,sizeof(size1)) ;
    memset(dep,0,sizeof(dep)) ;
    memset(son,0,sizeof(son)) ;
    memset(top,0,sizeof(top)) ;
    memset(fa,0,sizeof(fa)) ;
}
void dfs(int u)
{
    size1[u] = 1 ;son[u] = 0 ;
    for(int i = head[u] ; i != -1 ; i = next1[i])
    {
        int v = to[i] ;
        if(v==fa[u]) continue ;
        fa[v]=u;
        dep[v] = dep[u]+1;
        dfs(v) ;
        if(size1[v] > size1[son[u]])
            son[u] = v ;
        size1[u] += size1[v] ;
    }
}
void build(int u,int t)
{
    top[u] = t ;
    w[u] = ++sz ;
    if(son[u]) build(son[u],t) ;
    for(int i = head[u] ; i != -1 ; i = next1[i])
    {
        int v = to[i] ;
        if(v==fa[u]||v==son[u]) continue ;
        build(v,v) ;
    }
}
int query(int u,int v )
{
    int f1,f2,flag=0,ans=0;
    node a[2],b,c,d;
    f1 = top[u] ;
    f2 = top[v] ;
    a[0].Max=a[1].Max=-1;
    while(f1 != f2)
    {
      //  puts("==========");
        if(dep[f1] < dep[f2])
        {
            swap(f1,f2) ;
            swap(u,v) ;
            flag ^= 1;
        }
        ql = w[f1] ;qr = w[u] ;
        u = fa[f1] ;f1=top[u] ;
        find(1,sz,1,d) ;
        if(a[flag].Max==-1)
        {
            a[flag] = d ;
            continue ;
        }
        b = d ;
        d = a[flag] ;
        c.Max = max(d.Max,b.Max) ;
        c.Min = min(d.Min,b.Min) ;
        c.lans = max(d.lans,max(b.Max-d.Min,b.lans)) ;
        c.rans = max(d.rans,max(d.Max-b.Min,b.rans)) ;
        if(flag) ans = max(ans,c.rans) ;
        else ans = max(ans,c.lans);
        a[flag] = c ;
    }
    if(dep[u] < dep[v])
    {
         swap(u,v) ;
         flag ^= 1;
    }
    ql = w[v] ; qr = w[u] ;
    find(1,sz,1,d)  ;
    if(a[flag].Max!=-1){
        b = d ;
        d = a[flag] ;
        c.Max = max(d.Max,b.Max) ;
        c.Min = min(d.Min,b.Min) ;
        c.lans = max(d.lans,max(b.Max-d.Min,b.lans)) ;
        c.rans = max(d.rans,max(d.Max-b.Min,b.rans)) ;
        if(flag) ans = max(ans,c.rans) ;
        else ans = max(ans,c.lans);
        a[flag] = c ;
    }
    else a[flag] = d ;
    if(a[0].Max==-1)
    {
        return max(ans,a[1].rans) ;
    }
    else if(a[1].Max==-1)
    {
       // puts("-----------");
      // // cout << a[0].lans << "==" << a[0].rans << endl;
        return max(ans,a[0].lans) ;
    }
    ans = max(ans,a[1].rans);
    ans = max(ans,a[0].lans);
    ans = max(ans,a[1].Max-a[0].Min);
    return ans;
}
void ADD(int u,int v ,int c )
{
    int f1,f2;
    f1 = top[u];f2=top[v] ;
    val = c ;
    while(f1 != f2)
    {
        if(dep[f1] < dep[f2])
        {
            swap(f1,f2) ;
            swap(u,v) ;
        }
        ql=w[f1] ;qr=w[u] ;
        u = fa[f1] ;
        f1 = top[u] ;
        update(1,sz,1) ;
    }
    if(dep[u] >dep[v])
        swap(u,v) ;
    ql = w[u];qr=w[v] ;
    update(1,sz,1);
}
int next_int() {
    char c;
    int re = 0;
    c = getchar();
    while (c < ‘0‘ || c > ‘9‘) c = getchar();
    while (c >= ‘0‘ && c <= ‘9‘) {
        re = re*10+c-‘0‘;
        c = getchar();
    }
    return re;
}

int ee[maxn] ;
int main()
{
    int n,m,x,y,i,j;
    int T,c ;
    //freopen("in.txt","r",stdin);
    scanf("%d",&T);
    while( T-- )
    {
        n = next_int();
        memset(head,-1,sizeof(head)) ;
        top1=0;
        for( i = 1 ; i <= n ;i++)
        {
           // scanf("%d",&ee[i]) ;
           ee[i]=next_int();
        }
        for( i = 1 ; i < n ;i++)
        {
           // scanf("%d%d",&x,&y) ;
            x = next_int();
            y = next_int();
            Unit(x,y) ;
            Unit(y,x) ;
        }
        sz=0;
        init();
        dfs(1) ;
        build(1,1);
        for( i = 1 ; i <= n ;i++)
        {
            ql=w[i];
            vv.Max = ee[i];
            vv.Min = ee[i] ;
            vv.lans = vv.rans = 0;
            num[ql] = vv ;
        }
        insert(1,sz,1);
        m = next_int();
        while(m--)
        {
           //  scanf("%d%d%d",&x,&y,&c) ;
             x = next_int();
             y = next_int();
             c = next_int();
             printf("%d\n",query(x,y)) ;
             ADD(x,y,c) ;
        }
    }
    return 0 ;
}

  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<map>
#include<ctime>
#include<bitset>
#define LL long long
#define INF 999999
#define mod 20140518
#define maxn 100010
using namespace std;

int head[maxn],next1[maxn*2],to[maxn*2] ;
int top ,n ;
bool vi[maxn] ;

void Unit(int u,int v )
{
    next1[top] = head[u] ;to[top] = v ;
    head[u] = top++;
}
struct LCT
{
    int w[maxn],add[maxn],Max[maxn];
    int ch[maxn][2],pre[maxn] ;
    int L[maxn] ;
    int Min[maxn],ans[maxn] ;
    bool rev[maxn] ;
    void init()
    {
        memset(rev,0,sizeof(rev)) ;
        memset(ch,0,sizeof(ch)) ;
        memset(add,0,sizeof(add));
        memset(pre,0,sizeof(pre)) ;
        memset(Max,0,sizeof(Max)) ;
        memset(ans,0,sizeof(ans)) ;
        memset(Min,0,sizeof(Min)) ;
        memset(L,0,sizeof(L)) ;
    }
    void Add(int x ,int val)
    {
        if(x)
        {
            add[x] += val ;
            w[x] += val ;
            Max[x] += val ;
            Min[x] += val ;
        }
    }
    void update(int x )
    {
        Max[x] = max(w[x],max(Max[ch[x][0]],Max[ch[x][1]])) ;
        Min[x] = w[x];
        if(ch[x][1]) Min[x] = min(Min[ch[x][1]],Min[x]) ;
        if(ch[x][0]) Min[x] = min(Min[ch[x][0]],Min[x]) ;
        ans[x] = max(ans[ch[x][0]],max(0,ans[ch[x][1]])) ;
        if(ch[x][0]&&ch[x][1])ans[x] = max(ans[x],Max[ch[x][0]]-Min[ch[x][1]]) ;
        if(ch[x][0])ans[x] = max(ans[x],Max[ch[x][0]]-w[x]) ;
        if(ch[x][1])ans[x] = max(ans[x],w[x]-Min[ch[x][1]]) ;

        L[x] = max(L[ch[x][0]],max(0,L[ch[x][1]])) ;
        if(ch[x][0]&&ch[x][1])L[x] = max(L[x],Max[ch[x][1]]-Min[ch[x][0]]) ;
        if(ch[x][1])L[x] = max(L[x],Max[ch[x][1]]-w[x]) ;
        if(ch[x][0])L[x] = max(L[x],w[x]-Min[ch[x][0]]) ;
    }
    void down(int x )
    {
        if(add[x])
        {
            Add(ch[x][0],add[x]) ;
            Add(ch[x][1],add[x]) ;
            add[x]=0;
        }
        return ;
        if(rev[x])
        {
            swap(ch[x][0],ch[x][1]) ;
            rev[ch[x][0]] ^= 1;
            rev[ch[x][1]] ^= 1;
            rev[x] = 0;
        }
    }
    bool isroot(int x )
    {
        if(ch[pre[x]][0] != x && ch[pre[x]][1] != x )
            return true ;
        return false;
    }
    void pushdown(int x )
    {
        if(!isroot(x)) pushdown(pre[x]) ;
        down(x) ;
    }
    void rotate(int x,int f)
    {
        int y = pre[x],z = pre[y];
        ch[y][!f] = ch[x][f];
        pre[ ch[x][f] ] = y;
        pre[x] = pre[y];
        if(ch[z][0] == y)ch[z][0] = x;
        else if(ch[z][1] == y)ch[z][1] = x;
        pre[y] = x;
        ch[x][f] = y;
        update(y);
    }
    void splay(int x)
    {
        pushdown(x);
        while(!isroot(x))
        {
            if(isroot(pre[x]))rotate(x,ch[pre[x]][0] == x);
            else
            {
                int y = pre[x],z = pre[y];
                int f = (ch[z][0] == y);
                if(ch[y][f] == x)rotate(x,!f),rotate(x,f);
                else rotate(y,f),rotate(x,f);
            }
        }
        update(x);
    }
    void access(int u)
    {
        for(int f = 0 ; u ;u = pre[u])
        {
            splay(u);
            ch[u][1] = f ;
            update(u);
            f = u ;
        }
    }
    bool check(int a ,int b)
    {
        int x =a,y=b;
        access(y) ;
        for(int f = 0 ;x ;x = pre[x])
        {
            splay(x) ;
            if(!pre[x]) break ;
            f = x ;
        }
        for( ; ch[x][1] ; x = ch[x][1]);
        return x == b ;
    }
    void make_root(int x )
    {
        access(x) ;
        splay(x) ;
        rev[x] ^= 1;
    }
    void cut(int x,int y )
    {
        if(x==y||!check(x,y))
        {
            puts("-1") ;
            return ;
        }
        make_root(x) ;
        splay(y) ;
        pre[ch[y][0]] = pre[y] ;
        pre[y] = ch[y][0] = 0 ;
    }
    int find(int x,int y )
    {
        access(y) ;
        for( int f = 0 ; x ; x = pre[x])
        {
            splay(x) ;
            if(!pre[x])
            {
                int Max1 = 0 ;
                Max1 = max(ans[f],L[ch[x][1]]);
                if(ch[x][1])Max1 = max(Max1,Max[ch[x][1]]-w[x]) ;
                if(f)Max1 = max(Max1,w[x]-Min[f]) ;
                if(ch[x][1]&&f) Max1= max(Max1,Max[ch[x][1]]-Min[f]);
                return Max1;
            }
            ch[x][1] = f ;
            f = x ;
            update(x) ;
        }
        return -1;
    }
    void add1(int x ,int y ,int add)
    {
        access(y) ;
        for(int f = 0 ; x ; x = pre[x])
        {
            splay(x) ;
            if(!pre[x])
            {
                w[x] += add ;
                Max[x] += add ;
                Min[x] += add ;
                Add(f,add) ;
                Add(ch[x][1],add) ;
                return ;
            }
            ch[x][1] = f ;
            f = x ;
            update(x) ;
        }
    }
    void link(int x,int y )
    {
        make_root(x) ;
        pre[x]=y;
    }
}lct;
void dfs(int u,int f)
{
    for(int i = head[u]; i != -1; i=next1[i])
    {
        int v = to[i] ;
        if(v==f) continue ;
        dfs(v,u);
        lct.pre[v] = u;
    }
}
int next_int() {
    char ch;
    int res;
    bool neg;
    while (ch = getchar(), !isdigit(ch) && ch != ‘-‘)
        ;
    if (ch == ‘-‘) {
        neg = true;
        res = 0;
    } else {
        neg = false;
        res = ch - ‘0‘;
    }
    while (ch = getchar(), isdigit(ch))
        res = res * 10 + ch - ‘0‘;
    return neg ? -res : res;
}
int main()
{
    int n,m,i,j,k;
    int T,case1=0,u,v,c ;
   // freopen("in.txt","r",stdin);
    cin >> T ;
    while(T--)
    {
        scanf("%d",&n) ;
        lct.init();
        for( i = 1 ; i <= n ;i++)
        {
            lct.w[i] = next_int() ;
        //    lct.Max[i] = lct.Min[i] = lct.w[i];
        }
        top=0;
        memset(head,-1,sizeof(head)) ;
        for( i = 1 ; i < n ;i++)
        {
            u = next_int();
            v = next_int();
            Unit(u,v) ;
            Unit(v,u) ;
        }
        dfs(1,-1);
        scanf("%d",&m) ;
        while(m--)
        {
            //scanf("%d%d%d",&u,&v,&c) ;
            u = next_int();
            v = next_int();
            c = next_int();
            printf("%d\n",lct.find(u,v)) ;
            lct.add1(u,v,c) ;
        }
    }
    return 0 ;
}

  

时间: 2024-12-13 06:27:21

hdu 5052 Yaoge’s maximum profit的相关文章

Hdu 5052 Yaoge’s maximum profit(树链剖分)

题目大意: 给出一棵树,每个点有商店,每个商店都有一个价格,Yaoge每次从x走到y都可以在一个倒卖商品,从中得取利益,当然,买一顶要在卖之前.但是没次走过一条路,这条路上的所有商品都会增加一个v. 输出每次的最大利益. 思路分析: 很容易想到树链剖分,可是关键在于如何维护这样一个变量,使得每次都要让买的再卖的前面. 维护变量 ltr 和 rtl ,表示从左去右和从右去左. 剖分熟练的时候,判断x 和 y的深度,一步一步往上爬. 然后维护区间最大值和最小值,爬的时候更新答案. ...4921ms

HDU 5052 Yaoge’s maximum profit 裸树链剖分 2014 ACM/ICPC Asia Regional Shanghai Online

题意: 给定n个点的带点权树. 下面n行给出每个点点权表示每个点买卖鸡腿的价格 下面n-1行给出树边 下面Q个操作 Q行 u, v, val 从u走到v,过程中可以买一个鸡腿,然后到后面卖掉,输出max(0, 最大的收益) 然后给[u,v]路径上点点权+=val 思路: 树链剖分裸题 屌丝题解:点击打开链接 #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include &

HDU5052 Yaoge’s maximum profit(树链剖分)点权更新,经典题

Yaoge's maximum profit Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 662    Accepted Submission(s): 182 Problem Description Yaoge likes to eat chicken chops late at night. Yaoge has eaten to

HDU5052 Yaoge’s maximum profit(LCT)

典型的LCT操作,但是维护的是一个序列最左边减最右边的最小值,所以要维护左边减右边的最小值del[0]和一个右边减左边的最小值del[1](因为rev标记swap的时候对应的值也要交换).维护的时候del[0]可能是来自于左右儿子的del[0],也有可能是来自于左儿子的最小值减去右儿子及当前节点的值的最大值,还有就是当前节点减去右儿子的最大值,比赛的时候漏了当前节点减去右儿子的最大值因而WA了..- -0 #pragma warning(disable:4996) #include <iostr

hdu 5052 树链剖分

Yaoge’s maximum profit Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 982    Accepted Submission(s): 274 Problem Description Yaoge likes to eat chicken chops late at night. Yaoge has eaten too

HDU 5052 LCT

Yaoge's maximum profit Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 516    Accepted Submission(s): 150 Problem Description Yaoge likes to eat chicken chops late at night. Yaoge has eaten to

HDU 4002 Find the maximum(数论-欧拉函数)

Find the maximum Problem Description Euler's Totient function, φ (n) [sometimes called the phi function], is used to determine the number of numbers less than n which are relatively prime to n . For example, as 1, 2, 4, 5, 7, and 8, are all less than

HDU 1839 Delay Constrained Maximum Capacity Path(二分+最短路)

题目地址:HDU 1839 我去..原来这题这么简单...网络流中这种二分建图的方式做了一大堆了..这种题还能难倒我吗...白天一直没怎么看懂题,对题意懵懵懂懂的...晚上好好看了看题,这不就是网络流中练的最多的那种二分建图模型吗....只是把网络流算法改成最短路就行了..但是两个地方手残了没能在实验室当场A掉..sad... 这题就是二分最小容量,对满足容量的加边,对时间求最短路.如果最短时间比规定时间少的话就可以继续增加容量,直到不能增加为止. 代码如下: #include <iostrea

Maximum profit of stocks

https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Mock%20Interviews/Large%20E-Commerce%20Company/E-Commerce%20Company%20-%20Interview%20Problems%20-%20SOLUTIONS/On-Site%20Question%201%20-%20SOLUTION.ipyn