• hdu5293 Tree chain problem 树形dp+线段树


    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5293

    在一棵树中,给出若干条链和链的权值。求选取不相交的链使得权值和最大。


    比赛的时候以为是树链剖分就果断没去想,事实上是没思路。

    看了题解,原来是树形dp。话说多校第一场树形dp还真多。

    。。


    维护d[i],表示以i为根节点的子树的最优答案。

    sum[i]表示i的儿子节点(仅仅能是儿子节点)的d值和。

    那么答案就是d[root]。


    怎样更新d值

    d[i] = max(sum[i] , w[p]+sigma sum[j] - sigma d[j] );   p为以i为lca的链 。j为链上的点(注意:不须要减去d[i])

    也就是。对于i,

    要么是不选i,答案即sum[i]。他的儿子和。

    要么是选i,即找一条过i的链,链的权值 + 这棵子树上不在链上的距离链近期的点的d值和。


    维护链上的的sum和,d和 用线段树。

    先通过树的遍历序将树上的节点链话。然后区间改动,单点查询。(每一个点的信息是改点到根节点路径上的和)


    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    using namespace std;
    const int N = 100000+10;
    typedef long long ll;
    const int maxh = 25;
    int st[N],ed[N],clock;
    
    
    // ************************************
    #define Lson Ls,L,mid
    #define Rson Rs,mid+1,R
    
    const int maxn = 100000+10;
    const int inf = 100000000;
    struct Node{
        ll val, set;
        ll val2 , set2;
    }tree[N<<2];
    inline void update(Node& fa, Node& Ls, Node& Rs){
        fa.val = Ls.val + Rs.val;
        fa.val2 = Ls.val2 + Rs.val2;
    }
    inline void pushdown(Node& fa, Node& Ls, Node& Rs){
        if (fa.set != 0){
            Ls.val += fa.set; Ls.set += fa.set;
            Rs.val += fa.set; Rs.set += fa.set;
            fa.set = 0;
        }
        if (fa.set2 != 0){
            Ls.val2 += fa.set2; Ls.set2 += fa.set2;
            Rs.val2 += fa.set2; Rs.set2 += fa.set2;
            fa.set2 = 0;
        }
    
    }
    void insert(int v, int L, int R, int p, int q, ll delta,ll delta2){
        if(p<=st[2]&& q>=st[2]&& delta2) {
        }
        if (p<=L && R<=q){
            tree[v].val += delta;
            tree[v].set += delta;
    
            tree[v].val2 += delta2;
            tree[v].set2 += delta2;
            return;
        }
        int Ls = v<<1, Rs = Ls+1, mid = (L+R)/2;
        pushdown(tree[v], tree[Ls], tree[Rs]);
        if (q<=mid) insert(Lson, p, q, delta,delta2);
        else if (p>mid) insert(Rson, p, q, delta,delta2);
        else{
            insert(Lson, p, q, delta,delta2);
            insert(Rson, p, q, delta,delta2);
        }
    //    update(tree[v], tree[Ls], tree[Rs]);
    }
    ll query(int v, int L, int R,int ql, int qr){
        if(ql<=L && R<=qr){
            return tree[v].val;
        }
        int Ls = v<<1, Rs = Ls+1, mid = (L+R)/2;
        pushdown(tree[v], tree[Ls], tree[Rs]);
        ll ans = 0;
        if(qr<=mid) ans = query(Lson,ql,qr);
        else if(ql>mid) ans = query(Rson,ql,qr);
        else{
            ans = query(Lson,ql,qr) + query(Rson,ql,qr);
        }
    //    update(tree[v], tree[Ls], tree[Rs]);
        return ans ;
    }
    ll query2(int v, int L, int R,int ql, int qr){
        if(ql<=L && R<=qr){
            return tree[v].val2;
        }
        int Ls = v<<1, Rs = Ls+1, mid = (L+R)/2;
        pushdown(tree[v], tree[Ls], tree[Rs]);
        ll ans = 0;
        if(qr<=mid) ans = query2(Lson,ql,qr);
        else if(ql>mid) ans = query2(Rson,ql,qr);
        else{
            ans = query2(Lson,ql,qr) + query2(Rson,ql,qr);
        }
    //    update(tree[v], tree[Ls], tree[Rs]);
        return ans ;
    }
    
    // ***************************************
    
    
    
    
    ll d[N],sum[N];
    vector<int> g[N];
    vector<int> list[N];
    struct pp{
        int u,v,w;
    }p[N];
    int n,m,dep[N];
    int anc[N][maxh+1];
    
    void dfs(int x,int pre){
        st[x] = ++clock;
        anc[x][0] = pre;
        for(int i=0;i<g[x].size();i++)if(g[x][i]!=pre){
            int u = g[x][i];
            dep[u] = dep[x] + 1;
            dfs(u,x);
        }
        ed[x] = clock;
    }
    void lca_init(){
        clock = 0;
        dep[1] = 1;
        dfs(1,-1);
        for(int i=1;i<=maxh-1;i++){
            for(int j=1;j<=n;j++)
                if(anc[j][i-1]<0) anc[j][i] = -1;
                else anc[j][i] = anc[anc[j][i-1]][i-1];
        }
    }
    int swim(int x,int H){
        for(int i=0;H;i++){
            if(H&1) x = anc[x][i];
            H >>= 1;
        }
        return x;
    }
    int lca(int u,int v){
        if(dep[u]>dep[v]) swap(u,v);
        int H = dep[v]-dep[u];
        v = swim(v,H);
        if(u==v) return u;
        for(int k=maxh-1;k>=0;k--)
            if(anc[u][k]!=anc[v][k]){
                u = anc[u][k];
                v = anc[v][k];
            }
        return anc[u][0];
    }
    
    
    ll find(int u,int v,int la){
        ll ans = 0;
        ll s1 = query2(1,1,n,st[u],st[u]);
        ll s2 = query2(1,1,n,st[v],st[v]);
        ans = s1 + s2;
    
        ll d1 = query(1,1,n,st[u],st[u]);
        ll d2 = query(1,1,n,st[v],st[v]);
        ans -= d1 + d2;
    
        return ans+sum[la];
    }
    
    ll dfs_tree(int x,int pre){
        if(d[x]!=-1) return d[x];
        ll res = 0;
        sum[x] = 0;
        for(int i=0;i<g[x].size();i++)if(g[x][i]!=pre){
            int u = g[x][i];
            sum[x] += dfs_tree(u,x);
        }
        d[x] = sum[x];
    
        for(int i=0;i<list[x].size();i++){
            int id = list[x][i];
            ll tmp = p[id].w ;
            ll tmp1 = find(p[id].u,p[id].v,x);
            tmp += tmp1;
            d[x] = max(d[x] , tmp);
        }
    
        // update
    
        insert(1,1,n,st[x],ed[x],d[x],sum[x]);
        return d[x];
    }
    
    void solve(){
        memset(d,-1,sizeof(d));
        memset(tree,0,sizeof(tree));
        lca_init();
        for(int i=1;i<=n;i++) list[i].clear();
        for(int i=1;i<=m;i++){
            int u = p[i].u , v = p[i].v;
            int la = lca(u,v);
            list[la].push_back(i);
        }
        dfs_tree(1,-1);
    }
    
    
    int main(){
        int T;
        cin >> T;
        while(T--){
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++) g[i].clear();
            for(int i=1;i<=n-1;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                g[u].push_back(v);
                g[v].push_back(u);
            }
            for(int i=1;i<=m;i++){
                int u,v,w;
                scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].w);
            }
            solve();
            printf("%I64d
    ",d[1]);
        }
        return 0;
    }
    


  • 相关阅读:
    javascript之奇淫技巧
    nodejs的某些api~(一)node的流2
    javascript Object的新方法
    nodejs的某些api~(一)node的流1
    商城作品简介
    Javascript设计模式之观察者模式
    HTML 5 canvas globalCompositeOperation 属性
    设计模式----单利模式
    Centos6.8 安装tomcat8.5.11
    eclipse使用maven tomcat插件部署无法关联源代码
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6717594.html
Copyright © 2020-2023  润新知