hdu5293 Tree chain problem 树形dp+线段树

神奇的seepdtree SpeedTree是专门负责在游戏中“栽种”树木的程序,它不仅能够营造出非常真实的树木和森林效果,而且可以作为“零件”方便的嵌入到其他渲染引擎当中,为任何一款游戏带去优秀的画面。 立即下载

题目: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\n",d[1]);
    }
    return 0;
}


ABA分析方法 — 软硬件开发必备的一种分析问题绝佳套路 可能你从很多地方听过这个名词,无论是在软件开发还是硬件领域(比较典型的领域:汽车、消费电子、医疗等行业),ABA验证都是一种快速分析故障的一个方法,第一次听到这个词,当时是不是一脸懵逼,本文就深度带你了解下ABA的分析方法。简要概述就是:怀疑A模块导致系统故障,将B模块替换A模块,故障消失,再将A模块替换回来,故障复现,则说明A模块是导致系统故障的原因其实,ABA分析问题,可能很多人在工作中都或多或少用过这个方法,只是没有这个概念,说明白了就是控制变量和对比验证,没什么高大上的东西。 阅读详情

相关推荐

【Qualcomm高通音频】音效调试_录音文件播放有杂音,如何定位原因?

一、录音播放数据处理过程介绍 (1)TX方向 麦克风(硅麦克风或者主机体麦克风)采集模拟音频信号,经过内部CODEC芯片中的adc转换为数字信号,在经过高通音频DSP处理音效后编码为wav/aac/amr/mp3等格式文件。 (2)RX方向 音频文件经过解码、重采样还原为pcm数据,经过DSP处理音效后送到内部CODEC,然后经过DAC转换为模拟信号,送到喇叭。 二、分析步骤 1...

crow_ch的博客 5975

【HDU5293】Tree chain problem | 树形dp、LCA、树剖

题目大意: 给出一棵树,这棵树上分布着m条链,每条链都有一个权值,询问在保证选的链互不相交的情况下,最大的权值是多少 题目思路: en .. 卡了一晚上,卡到了lca,吐啦 首先将这m条链的lca求出来,把每条链的两个端点放到lca里面。 之后就可以进行树形dp了 令dp[i]表示,以i为根的子树选出不重复链的最大权值 那么对于一个根节点u,选择经过u的链,和不经过u的链两种选择: 如果不选择经过u的链:那么对于子树无限制,所以sum += dp[e] //e是u的孩子 如果选择经过u的

一只酷酷光儿的博客 571

CANoe SOME/IP实战:从ARXML到VCODM的完整配置与调试

本文详细介绍了使用CANoe进行SOME/IP通信测试的完整流程,从硬件环境准备、ARXML文件处理到VCODM文件配置与调试。通过实战技巧和常见问题解决方案,帮助工程师高效完成从ARXML到VCODM的配置,确保SOME/IP通信的稳定性和可靠性。

weixin_29169899的博客 467

【HDU5293】Tree chain problem(树形DP,树状数组)

Description 给定一棵树和很多条链,每条链有一个价值,要求选择一些不相交的链使得价值和最大。 Solution 设dp[u]dp[u]dp[u]为子树uuu内的答案,设sum[u]=∑v∈children(u)dp[v]sum[u]=∑v∈children(u)dp[v]sum[u]=\sum_{v\in children(u)}dp[v]。 考虑每条链在LCA处理。 ...

დ♂Hany01's Blog Space♂ღ 379

第二章 零差云控关节模组内部构造

对零差云控的eRob70I进行了拆解

SFY__优快云的博客 5987

NotImplementedError: Cannot copy out of meta tensor; no data! Please use torch.nn.Module.to_empty()

Please use torch.nn.Module.to_empty() instead of torch.nn.Module.to()输出(llama) (base) [root@localhost home]# nvidia-smi Unable to determine the device handle for GPU0000:09:00.0: Unknown Error。这是典型的“孤儿进程”,但它还是。(僵尸进程),占用 GPU 资源。如果进程仍然不消失,并且。,这意味着它的父进程是。

m0_61636632的博客 2096

HDU 5293 Tree chain problem【树形DP】

树形DP dp[i]dp[i]:表示以节点i为根的子树的最有情况 sum[i]sum[i]:表示∑dp[k]\sum dp[k](其中k是i的儿子) 转移情况有两种: 一是:dp[i]=sum[i]dp[i]=sum[i] 二是:选取一条链p,其中p的两个端点的LCA为节点i dp[i]=max(dp[i],val[p]+∑(sum[k])−∑(dp[k]))dp[i]=\max(dp[

Mr.Phoebe的专栏 722

GD32F303实战:用定时器4触发ADC2+DMA,实现10ms精准采样1024点的完整流程

本文详细介绍了在GD32F303微控制器上使用Timer4触发ADC2配合DMA传输,实现10ms精准采样1024点的完整方案。从硬件架构设计、时钟树配置到定时器参数计算,提供了完整的工程实现流程和常见问题排查方法,适用于工业传感器监测等高实时性场景。

weixin_29194693的博客 433

HDU 5293 树链剖分 + 树形DP

题目链接题意: 给定有nn个节点的树和mm条链(链连接两个顶点,且有权值),要求选出一部分链,使连接以后图的每个圈没有公共节点,问能够选出的链的权值和最大为多少?考虑树形DP。对于当前顶点uu,假设dp[u]dp[u]为以uu为根节点的子树所能够达到的最大目标值。 另外定义: 1.ww为当前考虑的链权值。 2.sum[u]=∑dp[k]sum[u] = \sum dp[k](kk为uu的子节

新熊君的博客 539

Palabos User Guide中文解读 | 第五章 | Palabos编程 (跳过了第四章Palabos-Java接口)

作者的话:本人在学习palabos时,发现国内中文资料甚少,恰好网上可以直接搜到palabos user guide这种英文资料,加之时间充裕,便打算开始翻译,翻了一节后发现这可能算侵权,就比较伤脑筋,突然想到自己写中文解读即可,便有了下面的博客。 Palabos User Guide Release 1.0 r1 Copyright © 2019 University of Geneva Jul...

Yulan Fang's notes. 2298

STM32实战开发(66):STM32图像处理开发教程

随着物联网、人工智能和嵌入式技术的不断发展,图像处理技术在嵌入式系统中的应用越来越广泛。图像处理不仅在视觉识别、安防监控、智能家居等领域中发挥着重要作用,也在工业自动化、医疗成像、无人驾驶等高科技领域中占据重要地位。而STM32凭借其强大的硬件性能和丰富的外设支持,成为了许多图像处理应用的理想平台。

2201_76125393的博客 1446

HDU 5293(树链剖分)

(http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106364#problem/A) 题意:给定一棵树,一些链,选出最多的链不相交。 解法:定义 sum[u] = sim(dp[v]) ( v = son[u] ) dp[u]为u这颗子树,最多能选的链数。 当有一条链a,b,lca(a,b)=u

r_clover的博客 384

检索增强生成(RAG)、微调(Fine-tuning)与知识蒸馏(Knowledge Distillation):核心差异与技术选型指南

在自然语言处理(NLP)领域,大型预训练语言模型(如GPT、BERT系列)的崛起彻底改变了技术生态。面对实际业务场景中模型效果优化与资源效率平衡的永恒命题,开发者主要依赖三大技术路径:检索增强生成(Retrieval-Augmented Generation, RAG)、模型微调(Fine-tuning)和知识蒸馏(Knowledge Distillation)。本文将通过技术原理拆解、典型应用场景对比和实战选型策略三个维度,深入解析这三种技术的本质差异。

fudaihb的博客 1828

HDU 5293 Tree chain problem [树链剖分+线段树+树形DP]

给出N个点的树,M条树链,树链有权,问在取出的树链互不相交的情况下,权值和最大是多少。

Asuna_acmer 795

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

HDU 5293 Tree chain problem 树形DP+LCA+树链剖分+线段树

Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,

JYZ's Blog 550

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

树形DP - hdu5293 Tree chain problem

题目: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给定一棵树,再给出若干树上的链,每条链拥有一个权值,问如何挑选这些链能使得权值之和最大,且被选中的链没有公共结点,求最大权值 思路: 看题解的过程中有看到用离线lca+时间戳+树形dp解法的,感觉那种解法会更加高大上...嗯不会离线lca所以这题用了树链剖分+线段

Keith_windniw的专栏 429

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

HDU 5293 Tree chain problem (树链剖分+LCA+树形DP)

#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:1024000000,1024000000") #define debug cout<<"YES\n"; #define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++) #de...

满月照亮的路 233

刷题总结——Tree chain problem(HDU 5293 树形dp+dfs序+树状数组)

题目: Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are m chain on the tree, Each chain has a certain weight. Coco would like to pick out some chai...

banzhangzhi8819的博客 235

2015多校第一场1006 hdu 5293 Tree chain problem

题意:给定一棵树,然后在给定一些链,链放在树上某条路径上,每条链有价值,要求取链,并且所取的链不能相交,使得取得的链的总价值最大。 做法:树上做动态规划,开个dp[i]表示第i个点为根的子树里面的取链最大价值,sum[i]表示i的儿子节点的dp值得和。考虑取一条链时,把一条链的路径上的所有sum[i]-dp[i]加起来(lca那点只需把sum[i]加进去就好了)再加上这条链的价值,这样做的目的是

ZJiaQ1994的博客 531

HDU 5293 Tree chain problem 树形DP

题意: 给出一棵\(n\)个节点的树和\(m\)条链,每条链有一个权值。 从中选出若干条链,两两不相交,并且使得权值之和最大。 分析: 题解 #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <set> #include &l...

weixin_30673611的博客 130

HDU 5293 Tree chain problem dfs序+树形dp

题意: 在树上给出一些链,链上有权值 求一个最大的链集合的权值和,集合内的链不相交 思路: 把每条链的状态放到lca(u,v)上,然后进行树形dp dp[u]有两种状态 1.不取链 dp[u]=∑dp[Son[u]] 2.取一个lca(x,y)==u的链加上 因为要取这条链,所以我们应该减掉子树上取了相交的链多加的值 因为点有点多,而且对于链操作 很容易想到dfs序或者树剖(

humeay的博客 409

HDU5293:Tree chain problem(树形dp & LCA)

Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1779    Accepted Submission(s): 577 Problem Description Coco has

junior19的博客 334

HDU 5293 Tree chain problem - 树形dp&树状数组优化

题目描述 题目大意: 给定一棵有 n 个点的树,以及 m 条树链,其中第 i 条树链 的价值为 wi,请选择一些没有公共点的树链,使得价值和最大。 1 ≤n,m≤ 100000。 Source:2015 Multi-University Training Contest 1 分析: 设f[u]为u为根的子树上选择没有公共点的树链所得的最大价值和。 转移方...

weixin_30483013的博客 246

HDU 5293(Tree chain problem-树链剖分)

Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 940    Accepted Submission(s): 248 Problem Description Coco has a tr

nike0good |Oier&ACMer | 熟能生巧 1099

hdu 5293 Tree chain problem【树状dp+dfs序+树状数组】

题目大意:在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大。解题思路:树形DP。设dp[i]表示i的子树下的最优权值和,sum[i]表示不考虑i点时子树的最优权值和,即(j是i的儿子),显然dp[i]>=sum[i]。那么问题是考虑i点时dp[i]的值是多少,假设有一条链通过i,且端点a和b都在i的子树里,即LCA(a,b)=i,如果考虑加上这条链的权值,那么a->i, b->i的

cdsszjj的博客 492
上一篇: 51NOD算法马拉松 最大值问题 离线预处理+set lower_bound
下一篇: hdu4305Lightning 生成树计数(基尔霍夫矩阵)+高斯消元+逆元
alpc_wt
博客等级 码龄12年 8粉丝 58原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值