BZOJ3252攻略

BZOJ3252攻略

题面:BZOJ

解析

博主从前在考场上做到过类似的题,当时并没有做出来。今天总算解决了,其实现在想来挺简单的,就是个简单的贪心,然后用线段树维护一下就行了。

代码


#include<cstdio>
#define N 200005
#define LL long long
#define mid ((l+r)>>1)
#define lc c[u][0]
#define rc c[u][1]
using namespace std;
inline int In(){
    char c=getchar(); int x=0,ft=1;
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
    for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
    return x*ft;
}
inline LL max(LL a,LL b){
    return a>b?a:b;
}
int n,K,val[N],h[N],e_tot=0;
struct E{ int to,nex; }e[N<<1];
inline void add(int u,int v){
    e[++e_tot]=(E){v,h[u]}; h[u]=e_tot;
    e[++e_tot]=(E){u,h[v]}; h[v]=e_tot;
}
int dfn[N],low[N],rk[N],fa[N],dfs_clock=0;
LL d[N],ans=0;
void dfs(int u,int pre){
    int child=0;
    d[u]=d[pre]+val[u]; fa[u]=pre;
    dfn[u]=++dfs_clock; rk[dfs_clock]=u;
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to; if(v!=fa[u]) dfs(v,u);
        ++child;
    }
    low[u]=dfs_clock;
}
int rt=0,T_tot=0,c[N<<1][2],pos[N<<1];
LL _mx[N<<1],lz[N<<1];
inline void PushUp(int u){
    _mx[u]=max(_mx[lc],_mx[rc]);
    pos[u]=pos[c[u][_mx[u]!=_mx[lc]]];
}
inline void PushDown(int u){
    if(lz[u]){
        lz[lc]+=lz[u]; _mx[lc]+=lz[u];
        lz[rc]+=lz[u]; _mx[rc]+=lz[u]; lz[u]=0;
    }
}
inline void Build(int l,int r,int& u){
    if(!u) u=++T_tot;
    if(l==r){ _mx[u]=d[rk[l]]; pos[u]=rk[l]; return; }
    Build(l,mid,lc); Build(mid+1,r,rc); PushUp(u);
}
inline void Modify(int L,int R,int C,int l,int r,int u){
    if(L<=l&&r<=R){ _mx[u]+=C; lz[u]+=C; return; }
    PushDown(u);
    if(L<=mid) Modify(L,R,C,l,mid,lc);
    if(R>mid) Modify(L,R,C,mid+1,r,rc);
    PushUp(u);
}
bool flag[N];
int main(){
    n=In(); K=In(); flag[0]=1;
    for(int i=1;i<=n;++i) val[i]=In();
    for(int i=1;i<n;++i) add(In(),In());
    dfs(1,0); Build(1,n,rt);
    for(int i=1;i<=K;++i){
        ans+=_mx[rt];
        for(int u=pos[rt];!flag[u];u=fa[u]){
            flag[u]=1;
            Modify(dfn[u],low[u],-val[u],1,n,rt);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

转载于:https://www.cnblogs.com/pkh68/p/10555014.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值