bzoj3252

3252: 攻略

Description

题目简述:树版[k取方格数]
众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏。今天他得到了一款新游戏《XX
半岛》,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景。所有场景和选择支构成树状
结构:开始游戏时在根节点(共通线),叶子节点为结局。每个场景有一个价值,现在桂马开启攻略之神模式,同
时攻略k次该游戏,问他观赏到的场景的价值和最大是多少(同一场景观看多次是不能重复得到价值的)
“为什么你还没玩就知道每个场景的价值呢?”
“我已经看到结局了。”

Input

第一行两个正整数n,k
第二行n个正整数,表示每个场景的价值
以下n-1行,每行2个整数a,b,表示a场景有个选择支通向b场景(即a是b的父亲)
保证场景1为根节点
n<=200000,1<=场景价值<=2^31-1

Output

输出一个整数表示答案

Sample Input

5 2
4 3 2 1 1
1 2
1 5
2 3
2 4

Sample Output

10
 
sol:显然每次都取最大的那条链一定是最优的(废话,难在怎么维护,每个点维护它到根的点权和,发现一个点被改掉以后整个子树都会被修改,所以搞出dfs序之后线段树上搞搞就好了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
  ll s=0; bool f=0; char ch=' ';
  while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();}
  while(isdigit(ch)) {s=(s<<3)+(s<<1)+(ch^48); ch=getchar();}
  return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
  if(x<0) {putchar('-'); x=-x;}
  if(x<10) {putchar(x+'0'); return;}
  write(x/10); putchar((x%10)+'0');
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=200005,M=400005;
int n,m,fa[N],clk=0,inc[N],ouc[N],ref[N];
ll a[N],val[N],ans=0;
bool del[N];
int tot=0,Next[M],to[M],head[N];
#define fi first
#define se second
#define Mp make_pair
struct Node
{
  pair<ll,ll> mx;
  ll lz;
}T[N<<2];
#define c1 (x<<1)
#define c2 (x<<1|1)
inline void Link(int x,int y)
{
  Next[++tot]=head[x]; to[tot]=y; head[x]=tot;
}
inline void Dfs(int x,int fat)
{
  int e;
  fa[x]=fat; val[x]=val[fat]+a[x]; inc[x]=++clk; ref[clk]=x;
  for(e=head[x];e;e=Next[e]) Dfs(to[e],x);
  ouc[x]=clk;
}
inline void PushUp(int x)
{
  T[x].mx=max(T[c1].mx,T[c2].mx);
}
inline void PushDown(int x)
{
  if(!T[x].lz) return;
  T[c1].mx.fi+=T[x].lz; T[c1].lz+=T[x].lz;
  T[c2].mx.fi+=T[x].lz; T[c2].lz+=T[x].lz;
  T[x].lz=0;
}
inline void Build(int x,int l,int r)
{
  if(l==r){T[x].mx=Mp(val[ref[l]],l); return;}
  int mid=(l+r)>>1;
  Build(c1,l,mid); Build(c2,mid+1,r);
  PushUp(x);
}
inline void Updata(int x,int l,int r,int ql,int qr,ll val)
{
  if(l==ql&&r==qr)
  {
    T[x].mx.fi+=val; T[x].lz+=val; return;
  }
  PushDown(x);
  int mid=(l+r)>>1;
  if(qr<=mid) Updata(c1,l,mid,ql,qr,val);
  else if(ql>mid) Updata(c2,mid+1,r,ql,qr,val);
  else Updata(c1,l,mid,ql,mid,val),Updata(c2,mid+1,r,mid+1,qr,val);
  PushUp(x);
}
int main()
{
  freopen("bzoj3252.in","r",stdin);
    int i,x,y;
    R(n); R(m);
  for(i=1;i<=n;i++) R(a[i]);
    for(i=1;i<n;i++) {R(x); R(y); Link(x,y);}
  Dfs(1,0);
  // for(i=1;i<=n;i++) cout<<ref[i]<<' '; putchar('\n');
  Build(1,1,n);
  for(i=1;i<=m;i++)
  {
    ans+=T[1].mx.fi;
    x=ref[T[1].mx.se];
    // cout<<"ans="<<ans<<' '<<"now="<<x<<endl;
    while((!del[x])&&x)
    {
      Updata(1,1,n,inc[x],ouc[x],-1*a[x]); del[x]=1; x=fa[x];
      // cout<<x<<' '<<inc[x]<<' '<<ouc[x]<<' '<<a[x]<<endl;
    }
  }
  Wl(ans);
  return 0;
}
/*
input
5 2
4 3 2 1 1
1 2
1 5
2 3
2 4
output
10
*/
View Code

 

posted @ 2019-07-23 21:12  yccdu  阅读(226)  评论(0编辑  收藏  举报