hdu5052 Yaoge’s maximum profit 树链剖分

来源:互联网 发布:计算机编程语言有哪些 编辑:程序博客网 时间:2024/05/16 05:27

一棵树上,从u走到v,在某点买入,咋之后的某点卖出,求最大利润。

维护正着走和反着走的最大利润。

#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#include<vector>#include<set>#include<map>#include<queue>#include<bitset>#define fi first#define se second#define pii pair<int,int>#define ll long long#define inf 1000000000#define eps 1e-8using namespace std;const int maxn=100005;int son[maxn],top[maxn],dep[maxn],fa[maxn],siz[maxn],id[maxn],fid[maxn];int sz;vector<int>g[maxn];int val[maxn];int n,q;struct Node{    int mi,mx;    int ans;    int o;    Node(int a,int b,int c,int d):mi(a),mx(b),ans(c),o(d){}    Node(){}}node[maxn<<2];int add[maxn<<2];void dfs(int u,int f){    siz[u]=1;    son[u]=0;    for(int i=0;i<g[u].size();i++) {        if(g[u][i]==f)            continue;        int v=g[u][i];        fa[v]=u;        dep[v]=dep[u]+1;        dfs(v,u);        if(siz[v]>siz[son[u]]) son[u]=v;        siz[u]+=siz[v];    }}void build(int u,int w){    id[u]=++sz;    fid[sz]=u;    top[u]=w;    if(son[u]) build(son[u],w);    for(int i=0;i<g[u].size();i++) {        int v=g[u][i];        if(v==fa[u]) continue;        if(v!=son[u]) build(v,v);    }}void T(){    int rt=(n+1)/2;    sz=0;    dep[rt]=0;    fa[rt]=0;    dfs(rt,0);    build(rt,rt);}void pushUp(int rt){    node[rt].mx=max(node[rt<<1].mx,node[rt<<1|1].mx);    node[rt].mi=min(node[rt<<1].mi,node[rt<<1|1].mi);    node[rt].ans=max(node[rt<<1].ans,node[rt<<1|1].ans);    node[rt].ans=max(node[rt].ans,node[rt<<1|1].mx-node[rt<<1].mi);    node[rt].o=max(node[rt<<1].o,node[rt<<1|1].o);    node[rt].o=max(node[rt].o,node[rt<<1].mx-node[rt<<1|1].mi);}void pushDown(int rt){    if(add[rt]==0) return;    node[rt<<1].mi+=add[rt];    node[rt<<1].mx+=add[rt];    node[rt<<1|1].mi+=add[rt];    node[rt<<1|1].mx+=add[rt];    add[rt<<1]+=add[rt];    add[rt<<1|1]+=add[rt];    add[rt]=0;}void update(int L,int R,int c,int l,int r,int rt){    if(L<=l&&R>=r) {        node[rt].mx+=c;        node[rt].mi+=c;        add[rt]+=c;        return;    }    pushDown(rt);    int m=((l+r)>>1);    //Node u={inf,-inf,0};    if(L<=m)        update(L,R,c,l,m,rt<<1);    if(R>m)        update(L,R,c,m+1,r,rt<<1|1);    pushUp(rt);}void update(int a,int b,int c){    int f1=top[a],f2=top[b];    while(f1!=f2) {        if(dep[f1]<dep[f2]) {            swap(f1,f2);            swap(a,b);        }        update(id[f1],id[a],c,1,n,1);        a=fa[f1]; f1=top[a];    }    if(dep[a]>dep[b]) swap(a,b);    update(id[a],id[b],c,1,n,1);}Node unite(Node a,Node b){    Node u;    u.mx=max(a.mx,b.mx);    u.mi=min(a.mi,b.mi);    u.ans=max(a.ans,b.ans);    u.ans=max(u.ans,b.mx-a.mi);    u.o=max(a.o,b.o);    u.o=max(u.o,a.mx-b.mi);    return u;}Node query(int L,int R,int l,int r,int rt){    if(L<=l&&R>=r)        return node[rt];    pushDown(rt);    Node u=Node(inf,-inf,0,0);    int m=((l+r)>>1);    if(L<=m)        u=unite(u,query(L,R,l,m,rt<<1));    if(R>m)        u=unite(u,query(L,R,m+1,r,rt<<1|1));    pushUp(rt);    return u;}int query(int u,int v){    int a = top[u], b = top[v];    Node lpath = Node(inf , -inf, 0,0), rpath = Node(inf, -inf, 0,0);    while(a != b){        if( dep[a] > dep[b]){            Node res = query(id[a], id[u],1,n,1);            //cout<<res.mi<<" "<<res.mx<<" "<<res.ans<<endl;            swap(res.ans, res.o);            lpath = unite(lpath, res);            u = fa[a];            a = top[u];        }        else{            Node res = query(id[b], id[v],1,n,1);            //cout<<res.mi<<" "<<res.mx<<" "<<res.ans<<endl;            rpath = unite(res, rpath);            v = fa[b];            b = top[v];        }    }    Node ans;    if( dep[u] < dep[v] ){        ans = query(id[u], id[v],1,n,1);    }    else{        ans = query(id[v], id[u],1,n,1);        swap(ans.ans,ans.o);    }    ans = unite(lpath, ans);    ans = unite(ans, rpath);    return ans.ans;}void buildTree(int l,int r,int rt){    add[rt]=0;    if(l==r) {        int a=fid[l];        node[rt].mi=node[rt].mx=val[a];        node[rt].ans=node[rt].o=0;        return;    }    int m=((l+r)>>1);    buildTree(l,m,rt<<1);    buildTree(m+1,r,rt<<1|1);    pushUp(rt);}int main(){    int t;    int a,b,c;    scanf("%d",&t);    while(t--) {        scanf("%d",&n);        for(int i=1;i<=n;i++) {            scanf("%d",&val[i]);            g[i].clear();        }        for(int i=0;i<n-1;i++) {            scanf("%d%d",&a,&b);            g[a].push_back(b);            g[b].push_back(a);        }        T();        buildTree(1,n,1);        //cout<<node[1].mi<<" "<<node[1].mx<<" "<<node[1].ans<<endl;        scanf("%d",&q);        while(q--) {            scanf("%d%d%d",&a,&b,&c);            printf("%d\n",query(a,b));            update(a,b,c);        }    }    return 0;}


0 0