题面

传送门

分析

此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做

这里给出DFS序+线段树的代码

我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x

每次从根节点走到x,将点归0,再把最大值累加

然而,修改操作怎么做呢?

这里当然可以树剖,但是还有代码量更小的做法

从x往父亲跳,每次将子树中的节点值都-v(v为当前节点的权值,当前节点权值变为0,从根到子树中的节点必须经过它,所有路径值之和-v)

然后加一个标记mark,如果这个节点之前被清零过就不用再跳了

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 200005
using namespace std;
int n,k;
struct edge{
int from;
int to;
int next;
}E[maxn<<1];
int size=0;
int head[maxn];
void add_edge(int u,int v){
size++;
E[size].from=u;
E[size].to=v;
E[size].next=head[u];
head[u]=size;
} int cnt=0;
int l[maxn],r[maxn],hash[maxn],mark[maxn];
//l,r为dfs序中子树的区间范围
//hash[i]表示dfs序中的第i个节点编号
//mark的含义见上方分析
long long a[maxn];
long long sum[maxn];
int fa[maxn];
void dfs(int x,int pa){
sum[x]=sum[pa]+a[x];
l[x]=++cnt;
hash[cnt]=x;
fa[x]=pa;
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(y!=pa){
dfs(y,x);
}
}
r[x]=cnt;
} struct node{
int l;
int r;
long long v;
long long mark;
int point;
}tree[maxn<<2];
void push_up(int pos){
if(tree[pos<<1].v>tree[pos<<1|1].v){
tree[pos].v=tree[pos<<1].v;
tree[pos].point=tree[pos<<1].point;
}else{
tree[pos].v=tree[pos<<1|1].v;
tree[pos].point=tree[pos<<1|1].point;
}
}
void build(int l,int r,int pos){
tree[pos].l=l;
tree[pos].r=r;
tree[pos].v=0;
tree[pos].mark=0;
if(l==r){
tree[pos].v=sum[hash[l]];
tree[pos].point=hash[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,pos<<1);
build(mid+1,r,pos<<1|1);
push_up(pos);
}
void push_down(int pos){
if(tree[pos].mark){
tree[pos<<1].v+=tree[pos].mark;
tree[pos<<1].mark+=tree[pos].mark;
tree[pos<<1|1].v+=tree[pos].mark;
tree[pos<<1|1].mark+=tree[pos].mark;
tree[pos].mark=0;
}
}
void update(int L,int R,int v,int pos){
if(L<=tree[pos].l&&R>=tree[pos].r){
tree[pos].v+=v;
tree[pos].mark+=v;
return;
}
push_down(pos);
int mid=(tree[pos].l+tree[pos].r)>>1;
if(L<=mid) update(L,R,v,pos<<1);
if(R>mid) update(L,R,v,pos<<1|1);
push_up(pos);
}
void change(int x){
while(x){
if(mark[x]) break;
mark[x]=1;
update(l[x],r[x],-a[x],1);//子树的值-1
x=fa[x];//向上跳
}
}
int main(){
// freopen("input.txt","r",stdin);
int u,v;
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(int i=1;i<n;i++){
scanf("%d %d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(1,0);
build(1,n,1);
long long ans=0;
for(int i=1;i<=k;i++){
ans=ans+tree[1].v;
change(tree[1].point);
}
printf("%lld",ans);
return 0;
}

BZOJ 3252题解(贪心+dfs序+线段树)的更多相关文章

  1. 【bzoj3252】攻略 贪心+DFS序+线段树

    题目描述 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景(scene),某 ...

  2. bzoj3252 攻略 贪心+dfs序+线段树

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3252 题解 有一个非常显然的贪心思路:每次选择目前走到那儿能够获得的新权值最大的点. 证明的话 ...

  3. BZOJ3252 攻略(贪心+dfs序+线段树)

    考虑贪心,每次选价值最大的链.选完之后对于链上点dfs序暴力修改子树.因为每个点最多被选一次,复杂度非常正确. #include<iostream> #include<cstdio& ...

  4. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  5. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  6. Codeforces Round #442 (Div. 2)A,B,C,D,E(STL,dp,贪心,bfs,dfs序+线段树)

    A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...

  7. DFS序+线段树(bzoj 4034)

    题目链接 题目就不多说了. 本题目,可以用dfs序+线段树做:题目给定了一棵树,树上节点告诉了权值.我们可以先将这棵树进行dfs将一棵树变成线性结构:如图 变成这样后,然后就可以用线段树. 操作1:也 ...

  8. BZOJ1103 [POI2007]大都市meg dfs序 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...

  9. CodeForces 877E Danil and a Part-time Job(dfs序+线段树)

    Danil decided to earn some money, so he had found a part-time job. The interview have went well, so ...

随机推荐

  1. spring动态调用方法

    有的时候为了程序的灵活性,需要根据参数动态的调用方法.代码框架大致spring为主,下面是具体代码: 接口: 实现类(实现类中有一个从spring容器中取的对象) 这是最初我直接用反射去调用的代码: ...

  2. 【leetcode】1131. Maximum of Absolute Value Expression

    题目如下: Given two arrays of integers with equal lengths, return the maximum value of: |arr1[i] - arr1[ ...

  3. Ubuntu「一键」设置全局代理

    Ubuntu「一键」设置代理 sonictl note: the DNS problem may be still there. Except proxychains. WSL (Windows Su ...

  4. 手把手搭建K3cloud插件开发环境

    最近几天在配置K3cloud开发环境,发现不论是产品论坛还是百度出来的结果,都不够满意,很多大咖给提供的环境搭建手册都是那个云山雾罩的PPT 也就是这个open.kingdee.com/K3Cloud ...

  5. phpstudy升级5.7

    1:备份当前数据库数据. 最好是导成 SQL 文件 2:备份 PhpStudy 下的 MySQL 文件夹.以防升级失败.还可以使用旧版本的数据库 3:下载MySQL5.7.解压.然后放在 PhpStu ...

  6. setData 机制

    解释:setData 函数,用于将数据,从逻辑层发送到视图层,当开发者调用 setData 后,数据的变化,会引起视图层的更新.参数说明 属性 类型 是否必填 描述 data Object 是 这次要 ...

  7. 【rust】rust安装,运行第一个Rust 程序 (1)

    安装 Rust 在 Unix 类系统如 Linux 和 macOS 上,打开终端并输入: curl https://sh.rustup.rs -sSf | sh 回车后安装过程出现如下显示: info ...

  8. 【noip2016提高组day2T3】【愤怒的小鸟】状压dp转移时的集合包含

    (上不了p站我要死了,图来自百度,侵权度娘背锅) 调死我了... 标题就说明了,死在了集合包含上.因为这道题与其他的状压题不同,其他的题基本上都是要求集合不重合,而这道题完全是可以的. 废话不多说,先 ...

  9. hdu_1231(最大连续子序列)

    http://acm.hdu.edu.cn/showproblem.php?pid=1231 最长公共子序列: 方法1:暴力枚举所有区间的连续和,维护最大和 复杂度O(n^3)-->因为求区间和 ...

  10. Supervised pre-trainning有监督预训练

    如我们有一个分类任务,数据库很小,这时还是需要通过预训练来避免深度模型的过拟合问题的,只不过预训练是通过在一个大的数据库上(比如imagenet),通过有监督的训练来完成的.这种有监督预训练加小的数据 ...