传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3252
显然每次走最大的路径
dfs序+线段树维护
每个点最多修改一次
Code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
vector<int>G[maxn];
int getint(){
int res=0;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))res=res*10+c-'0',c=getchar();
return res;
}
int n,k,tot;
int fa[maxn],in[maxn],out[maxn],w[maxn],rmp[maxn<<1],vis[maxn],sum[maxn<<1];
void dfs(int u){
in[u]=++tot;rmp[tot]=u;
for(int i=0,v;i<G[u].size();i++){
if((v=G[u][i])!=fa[u]){
fa[v]=u;
dfs(v);
}
}out[u]=++tot;
}
typedef long long LL;
struct seg{
struct node{
LL lazy;
LL mx;
int ps;
node(){lazy=0;mx=0;ps=0;}
}t[maxn<<3];
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define L i<<1
#define R i<<1|1
void rz(int i){
if(t[L].mx>t[R].mx)
t[i].mx=t[L].mx,t[i].ps=t[L].ps;
else t[i].mx=t[R].mx,t[i].ps=t[R].ps;
}
void pushdown(int i,int l,int r){
if(t[i].lazy){
int mid=(l+r)>>1;
t[L].lazy+=t[i].lazy;
t[L].mx+=t[i].lazy;
t[R].lazy+=t[i].lazy;
t[R].mx+=t[i].lazy;
t[i].lazy=0;
}
}
void Change(int i,int l,int r,int l0,int r0,int d){
if(l0<=l&&r0>=r){
t[i].lazy+=d;
t[i].mx+=d;return;
}pushdown(i,l,r);
int mid=(l+r)>>1;
if(l0<=mid)Change(lson,l0,r0,d);
if(r0>mid) Change(rson,l0,r0,d);
rz(i);
}
void build(int i,int l,int r){
if(l==r){
t[i].ps=l;
return;
}int mid=(l+r)>>1;
build(lson);build(rson);rz(i);
}
int Max(){return t[1].ps;}
}T;
int main(){
n=getint();k=getint();
for(int i=1;i<=n;i++)w[i]=getint();
for(int i=1;i<n;i++){
int u=getint(),v=getint();
G[u].push_back(v);
G[v].push_back(u);
}dfs(1);
T.build(1,1,2*n);
for(int i=1;i<=n;i++)T.Change(1,1,2*n,in[i],2*n,w[i]);
for(int i=1;i<=n;i++)T.Change(1,1,2*n,out[i],2*n,-w[i]);
LL ans=0;
while(k--){
int u=rmp[T.Max()];
while(u&&!vis[u]){
ans+=w[u];
T.Change(1,1,2*n,in[u],2*n,-w[u]);
T.Change(1,1,2*n,out[u],2*n,w[u]);
vis[u]=2333;u=fa[u];
}
}cout<<ans<<endl;
return 0;
}