题解:

首先贪心的会发现我们每次一定会选当前权值和最大的那个

然后在于怎么维护这个最大值

我们发现每个修改实际上是对沿途所有点的子树的修改

所以用线段树维护就可以了。。

另外注意有重复部分,但一定是包含关系所以比较好处理

代码:

#include <bits/stdc++.h>
using namespace std;
#define IL inline
#define ll long long
#define rint register ll
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define mid ((h+t)/2)
char ss[<<],*A=ss,*B=ss;
char gc()
{
return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?EOF:*A++;
}
template<class T> void read(T &x)
{
rint f=,c; while (c=gc(),c<||c>) if (c=='-') f=-; x=c^;
while (c=gc(),<c&&c<) x=(x<<)+(x<<)+(c^); x*=f;
}
const ll INF=1e9;
const ll N=3e5;
ll n,m,k,l,v[N],head[N],maxn[N],minn[N],sum[N],fa[N],cnt,ans;
struct re{
ll a,b;
}a[N];
const ll N2=N*;
ll data1[N2],data2[N2],data3[N2],lazy1[N2],lazy2[N2],real2[N2];
void arr(ll x,ll y)
{
a[++l].a=head[x];
a[l].b=y;
head[x]=l;
}
IL void down(ll x)
{
if (!lazy1[x]) return;
lazy1[x*]=lazy1[x*+]=lazy1[x];
lazy2[x*]+=lazy2[x];
lazy2[x*+]+=lazy2[x];
data3[x*]+=lazy2[x]; data3[x*+]+=lazy2[x];
data2[x*]=lazy1[x]; data2[x*+]=lazy1[x];
lazy1[x]=lazy2[x]=;
}
IL void updata(ll x)
{
if (data3[x*]<data3[x*+])
{
data2[x]=data2[x*+];
data1[x]=data1[x*+];
data3[x]=data3[x*+];
} else
{
data2[x]=data2[x*];
data1[x]=data1[x*];
data3[x]=data3[x*];
}
}
void build(ll x,ll h,ll t)
{
if (h==t)
{
data1[x]=real2[h]; return;
}
build(x*,h,mid); build(x*+,mid+,t);
}
void change(ll x,ll h,ll t,ll h1,ll t1,ll k1,ll k2)
{
if (h1<=h&&t<=t1)
{
lazy1[x]=k1; lazy2[x]+=k2; data3[x]+=k2; data2[x]=k1;
return;
}
down(x);
if (h1<=mid) change(x*,h,mid,h1,t1,k1,k2);
if (mid<t1) change(x*+,mid+,t,h1,t1,k1,k2);
updata(x);
}
void dfs1(ll x)
{
ll u=head[x];
if (!u)
{
real2[++cnt]=x;
return;
}
while (u)
{
ll vv=a[u].b;
dfs1(vv);
u=a[u].a;
}
}
void dfs(ll x,ll y)
{
ll u=head[x]; sum[x]=y+v[x];
if (!u)
{
minn[x]=maxn[x]=++cnt;
real2[cnt]=x;
change(,,n,cnt,cnt,,sum[x]);
return;
}
while (u)
{
ll vv=a[u].b;
dfs(vv,y+v[x]);
minn[x]=min(minn[x],minn[vv]);
maxn[x]=max(maxn[x],maxn[vv]);
u=a[u].a;
}
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
read(n); read(k);
rep(i,,n) read(v[i]);
rep(i,,n) minn[i]=INF;
rep(i,,n-)
{
ll x,y;
read(x); read(y); arr(x,y); fa[y]=x;
}
dfs1();
build(,,n); cnt=;
dfs(,);
rep(i,,k)
{
ll x=data1[],y=data2[],z=data3[];
ans+=z;
int kk1=minn[x]-,kk2=minn[x];
while (x!=y)
{
if (kk1>=minn[x]) change(,,n,minn[x],kk1,x,-(sum[x]-sum[y]));
if (kk2<=maxn[x]) change(,,n,kk2,maxn[x],x,-(sum[x]-sum[y]));
kk1=minn[x]-; kk2=maxn[x]+;
x=fa[x];
}
}
cout<<ans<<endl;
return ;
}

【BZOJ3252】攻略的更多相关文章

  1. [bzoj3252]攻略_dfs序_线段树_贪心

    攻略 bzoj-3252 题目大意:给定一棵n个节点的有根树,点有点权.让你选出至多k个节点,使得他们到根的链的并最大. 注释:$1\le n\le 2\cdot 10^5$,$1\le val_i\ ...

  2. BZOJ3252: 攻略

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

  3. BZOJ3252攻略——长链剖分+贪心

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

  4. BZOJ3252 攻略 [树链剖分]

    题目传送门 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1169  Solved: 554[Submit][Status][Discuss] ...

  5. bzoj3252 攻略 dfs序+线段树

    题目传送门 题目大意:给出一棵树,1为根节点,每个节点都有权值,每个叶子节点都是一个游戏的结局,选择k个游戏结局,使得权值总和最大,同一个节点不会被重复计算. 思路:这道题最关键的是要想到一个性质,就 ...

  6. bzoj3252攻略(线段树+dfs序)

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

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

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

  8. BZOJ3252: 攻略 可并堆

    网上有很多人说用dfs序+线段树做...其实stl的堆可以...可并堆可以...很多奇奇怪怪的东西都能做... 可并堆比较好想...也比较好写... 分析: 首先,这是一个网络流做不了的题...数据太 ...

  9. BZOJ3252 攻略 贪心、长链剖分

    传送门 给树竟直接给父子关系!!!真良心 首先一个贪心策略:每一次选择的链一定是所有链中权值最大的.这应该比较显然 那么我们接下来考虑如何维护这个贪心.我们可以使用长链剖分进行维护,对权值进行长链剖分 ...

  10. bzoj3252: 攻略(贪心)

    /* 因为权值都是正的, 所以贪心的正确性能保证 然后重链贪心跑一下就好了 */ #include<cstdio> #include<algorithm> #include&l ...

随机推荐

  1. SQL NOLOCK大杂烩

    今天碰到NOLOCK 的问题,就查阅了一些资料,做了相关了解:总结了比较经典,朴实的两篇在此. 电梯直达: SQL Server 中WITH (NOLOCK)浅析 文章本想大篇幅摘抄,因为担心链接失效 ...

  2. Linux内核初探

    内存管理之内存寻址 内存管理是迄今为止Unix内核中最复杂的活动 虚拟内存: 所有新近的Unix系统都提供一种有用的抽象, 叫作虚拟内存(virtual memory): 虚拟内存可以理解为一种逻辑层 ...

  3. Anaconda安装新模块

    如果使用import导入的新模块没有安装,则会报错,下面是使用Anaconda管理进行安装的过程:1.打开Anaconda工具,如图: 2.可通过输入 conda list 查看已安装的模块 3.如果 ...

  4. python实现求最大公约数与最小公倍数

    记录python实现最大公约数&最小公位数两种算法 概念 最大公约数:指两个或多个整数共有约数中最大的一个 最小公倍数:两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就 ...

  5. Mysql41道练习题

    1.自行创建测试数据 2.查询“生物”课程比“物理”课程成绩高的所有学生的学号.ps:针对的是自己的生物成绩比物理成绩高,再把符合条件的学生的学号查出来: # 查到 生物 和 物理的 id: sele ...

  6. JMeter 中_time 函数的使用(时间戳、当前时间)

    有时在接口测试时,其参数需要为时间戳或者是日期格式的数据.针对此问题,可以使用JMeter自带的_time 函数来解决以上问题 操作步骤: 1.通过函数助手,生成一个_time 函数: 2.如果参数为 ...

  7. Confluence 6 使用 Apache 和 mod_proxy

    Atlassian 应用允许用户使用反向代理,但是 Atlassian 并不会为这个功能的配置提供支持.因此,Atlassian 也不能保证能够为这些配置提供任何支持. 如果你在配置上有任何需求,请参 ...

  8. Android CTS Test

    什么是CTS测试?了解这个问题前,我们先来搜索了解一遍“Google GMS 认证”.GMS全称为GoogleMobile Service,即谷歌移动服务.说白了GMS其实就是一系列谷歌的应用集合.谷 ...

  9. mac 端口占用问题

    查看端口号 终端输入:sudo lsof -i tcp:port 将port换成被占用的端口(如:8086.9998) 将会出现占用端口的进程信息. 杀死占用端口的PID进程 找到进程的PID,使用k ...

  10. java多线程快速入门(十八)

    Lock锁是JDK1.5之后推出的并发包里面的关键字(注意捕获异常,释放锁) Lock与synchronized的区别 Lock锁可以人为的释放锁(相当于汽车中的手动挡) synchronized当线 ...