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
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 */
河田は河田、赤木は赤木……。
私は誰ですか。教えてください、私は誰ですか。
そうだ、俺はあきらめない男、三井寿だ!