BZOJ 3252题解(贪心+dfs序+线段树)
题面
分析
此题做法很多,树形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序+线段树)的更多相关文章
- 【bzoj3252】攻略 贪心+DFS序+线段树
题目描述 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏. 今天他得到了一款新游戏<XX半岛>,这款游戏有n个场景(scene),某 ...
- bzoj3252 攻略 贪心+dfs序+线段树
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3252 题解 有一个非常显然的贪心思路:每次选择目前走到那儿能够获得的新权值最大的点. 证明的话 ...
- BZOJ3252 攻略(贪心+dfs序+线段树)
考虑贪心,每次选价值最大的链.选完之后对于链上点dfs序暴力修改子树.因为每个点最多被选一次,复杂度非常正确. #include<iostream> #include<cstdio& ...
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- 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 ...
- DFS序+线段树(bzoj 4034)
题目链接 题目就不多说了. 本题目,可以用dfs序+线段树做:题目给定了一棵树,树上节点告诉了权值.我们可以先将这棵树进行dfs将一棵树变成线性结构:如图 变成这样后,然后就可以用线段树. 操作1:也 ...
- BZOJ1103 [POI2007]大都市meg dfs序 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...
- 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 ...
随机推荐
- layui 动态添加 表格数据
静态表格: <table class="layui-table" id="table" lay-filter="table"> ...
- fs.mkdir
fs.mkdir(path[, mode], callback) 要求父目录必须存在 let fs = require('fs'); fs.mkdir('./c/b/a', res=>{ // ...
- 一个简单mock-server 解决方案
參考: 测试利器之Mock server 介紹 moco server - download Mockman - download 各种Mock工具比较 JMockit中文网 MockWebServe ...
- 1.docker容器技术基础入门
内容来自:https://www.cnblogs.com/marility/p/10215062.html https://blog.51cto.com/gouyc/2310785?source=dr ...
- Rails3:使用bundler管理gems
Rails3:使用bundler管理gems bundler 是一套为了 Rails3 所打造的全新 Gem dependencies 管理工具:一套基于 Rubygems 的更高阶套件管理工具,适合 ...
- java:集合输出之Iterator和ListIterator二
java:集合输出之Iterator和ListIterator二 ListIterator是Iterator的子接口,Iterator的最大特点是,能向前,或向后迭代.如果现在要想双向输出的话,则只能 ...
- vue组件样式scoped
1.vue组件中的样式如果没加scrped,样式代表的是全局样式(避免组件之间样式的冲突).加了属性代表是模块化的. 其他组件引用button组件 上面分析了单个组件渲染后的结果,那么组件互相调用之后 ...
- Django orm(1)
目录 一.orm查询 1.1配置测试脚本 1.1.1Django终端打印SQL语句的配置 1.2单表操作 1.2.1创建数据 1.2.2修改数据 1.2.3删除数据 1.2.4查询数据 1.2.5计数 ...
- ipcloud上传裁切图片
主页: <!doctype html> <html> <head> <meta charset="utf-8"> <meta ...
- HDU - 6578 Blank DP + 滚动数组
HDU - 6578 Blank 题意 给你\(\{0,1,2, 3\}\)四个数,分别填入长度为\(n\)的数列中,有\(m\)个限制条件,\(l_{i}, r_{i}, x_{i}\)表示在\([ ...