题面

传送门

分析

此题做法很多,树形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. transform-origin属性

    一.transform-origin的作用 transform-origin改变元素基点 (transform-origin是变形原点,原点就是元素绕着旋转或变形的点) 注意:该属性只有在设置了tra ...

  2. iOS之UIDatePicker

    这个还要取决于手机系统设置

  3. 死锁(deadlocks)

    1.定义 所谓死锁<DeadLock>: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象.若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了 ...

  4. ZeroMQ的进阶

    上一篇博文我们对ZeroMQ的经典模式做了写Demo让他跑起来了,但实际开发中我们可能面临一些远比上述复杂的场景.这时候我们需要进一步的对经典模式进行扩展,所幸ZeroMQ已经为我们做好了准备工作. ...

  5. R list和data frame 排序

    pathway_name = rownames(g1) tm <- list('P-value' = c(), 'Pathway_name' = c()) :dim(g1)[]){ result ...

  6. Java异常处理的基础知识

    Java中的异常捕获语句 Try{ //可能发生运行错误的代码: } catch(异常类型 异常对象引用){ //用于处理异常的代码 } finally{ //用于“善后” 的代码 } Java 中所 ...

  7. uploadify上传插件参数的一些设置

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. SVM 笔记整理

    支持向量机 一.支持向量机综述 1.研究思路,从最特殊.最简单的情况开始研究 基本的线性的可分 SVM 解决二分类问题,是参数化的模型.定义类标记为 \(+1\) 和 \(-1\)(区别于感知机,感知 ...

  9. Linux内核调试方法总结之栈帧

    栈帧 栈帧和指针可以说是C语言的精髓.栈帧是一种特殊的数据结构,在C语言函数调用时,栈帧用来保存当前函数的父一级函数的栈底指针,当前函数的局部变量以及被调用函数返回后下一条汇编指令的地址.如下图所示: ...

  10. 20160711--C# 委托的三种调用示例(同步调用 异步调用 异步回调)【转载】

    首先,通过代码定义一个委托和下面三个示例将要调用的方法: 代码如下: public delegate int AddHandler(int a,int b); public class 加法类 { p ...