bzoj 3252: 攻略 (线段树+DFS序)
来源:互联网 发布:高清矩阵厂家 编辑:程序博客网 时间:2024/05/21 19:35
题目描述
传送门
题目大意:选出K条从叶子节点到根节点的路径,使路径上的权值之和最大。注意每个点的权值只能被计算一次。
题解
看到这道题的第一反应是最大费用最大流。对于每条边只有第一次流的时候有价值。
那么根据这个思路,我们其实就是每次选取一条权值之和最大的路径加入答案,因为每个点的权值只能计算一次,所以路径上的点子树中所有叶子几点都要减去这个点的价值,就是用线段树维护每个点到根的距离。
按照只有叶子节点的dfs序建树,这样每次修改就是连续区间了。
代码
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define LL long long #define N 400003using namespace std;int tot,nxt[N],point[N],v[N],pos[N],l[N],r[N],pd[N],mark[N],sz,n,m,fa[N];LL tr[N*4],val[N],sum[N],delta[N];void add(int x,int y){ tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;}void dfs(int x,int f){ sum[x]=sum[f]+val[x]; bool pd=false; for (int i=point[x];i;i=nxt[i]) { if (v[i]==f) continue; pd=true; } if (!pd) { l[x]=r[x]=++sz; pos[sz]=x; return; } l[x]=sz+1; for (int i=point[x];i;i=nxt[i]) { if (v[i]==f) continue; fa[v[i]]=x; dfs(v[i],x); } r[x]=sz;}void update(int now){ if (tr[now<<1]>tr[now<<1|1]) tr[now]=tr[now<<1],mark[now]=mark[now<<1]; else tr[now]=tr[now<<1|1],mark[now]=mark[now<<1|1];}void build(int now,int l,int r){ if (l==r) { tr[now]=sum[pos[l]]; mark[now]=pos[l]; return; } int mid=(l+r)/2; build(now<<1,l,mid); build(now<<1|1,mid+1,r); update(now);}void pushdown(int now){ if (delta[now]){ tr[now<<1]+=delta[now]; delta[now<<1]+=delta[now]; tr[now<<1|1]+=delta[now]; delta[now<<1|1]+=delta[now]; delta[now]=0; }}void query(int now,int l,int r,int ll,int rr,LL v){ if (ll<=l&&r<=rr) { tr[now]-=v; delta[now]-=v; return; } int mid=(l+r)/2; pushdown(now); if (ll<=mid) query(now<<1,l,mid,ll,rr,v); if (rr>mid) query(now<<1|1,mid+1,r,ll,rr,v); update(now);}void solve(int x){ while (x) { if (pd[x]) break; pd[x]=1; query(1,1,sz,l[x],r[x],val[x]); x=fa[x]; }}int main(){ freopen("a.in","r",stdin); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%lld",&val[i]); for (int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); } dfs(1,0); build(1,1,sz); LL ans=0; for (int i=1;i<=m;i++){ ans+=tr[1]; solve(mark[1]); } printf("%lld\n",ans);}
阅读全文
0 0
- BZOJ 3252攻略 dfs序+线段树
- bzoj 3252: 攻略 (线段树+DFS序)
- 【BZOJ】【P3252】【攻略】【题解】【贪心+dfs序+线段树】
- 3252: 攻略 dfs序+线段树
- BZOJ 3252 攻略 线段树
- bzoj 4551(DFS序+线段树)
- BZOJ 3235 攻略 贪心+线段树+dfs序列
- dfs序+线段树 BZOJ3252 攻略
- bzoj3252攻略 贪心+dfs序+线段树
- bzoj 3306: 树 dfs序+线段树
- bzoj 4530(DFS序+线段树合并)
- BZOJ 1103 DFS序+线段树
- BZOJ 4034 线段树+DFS序
- BZOJ 2819 DFS序+线段树
- DFS序+线段树(bzoj 4034)
- 【BZOJ 3306】树【LCA、DFS序、线段树】
- BZOJ 4551 树 dfs序+线段树 / 并查集
- BZOJ 4034 HAOI2015 T2 DFS序+线段树
- vivado 设置 多线程编译
- (转)献给迷茫中的量化工作者
- 在struts2中 使用poi出现报错
- JAVA编程思想笔记--泛型
- bzoj3560 DZY Loves Math V
- bzoj 3252: 攻略 (线段树+DFS序)
- 剑指offer-跳台阶
- 关于 link monitor exit process_flag
- (转)郭广昌:复星账上有400亿现金,未来十年一切围绕C2M战略
- Android--简单计算器
- Servlet
- Linux 修改Oracle数据库字符集
- thrift简单使用
- 特点