dfs序+线段树 BZOJ3252 攻略
3252: 攻略
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 496 Solved: 211
[Submit][Status][Discuss]
Description
题目简述:树版[k取方格数]
众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏。
今天他得到了一款新游戏《XX半岛》,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景。所有场景和选择支构成树状结构:开始游戏时在根节点(共通线),叶子节点为结局。每个场景有一个价值,现在桂马开启攻略之神模式,同时攻略k次该游戏,问他观赏到的场景的价值和最大是多少(同一场景观看多次是不能重复得到价值的)
“为什么你还没玩就知道每个场景的价值呢?”
“我已经看到结局了。”
Input
第一行两个正整数n,k
第二行n个正整数,表示每个场景的价值
以下n-1行,每行2个整数a,b,表示a场景有个选择支通向b场景(即a是b的父亲)
保证场景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
HINT
对于100%的数据,n<=200000,1<=场景价值<=2^31-1
dfs序+线段树的模板吧……
函数传参不要写错!!!!!!
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define inf 1000000000000000ll 7 int n,k,cnt,tot; 8 long long ans; 9 long long val[200010],sum[200010]; 10 int head[200010],getin[200010],getout[200010],oula[200010],fa[200010]; 11 bool check[200010]; 12 struct data{ 13 int next,to; 14 }edge[400010]; 15 struct dt{ 16 long long mx,loc,tag; 17 }segtree[800010]; 18 void add(int start,int end){ 19 edge[++cnt].next=head[start]; 20 edge[cnt].to=end; 21 head[start]=cnt; 22 fa[end]=start; 23 } 24 void dfs(int u){ 25 getin[u]=++tot; 26 oula[tot]=u; 27 for(int i=head[u];i;i=edge[i].next){ 28 sum[edge[i].to]=sum[u]+val[edge[i].to]; 29 dfs(edge[i].to); 30 } 31 getout[u]=tot; 32 } 33 void up(int pos){ 34 segtree[pos].mx=0; 35 if(segtree[pos<<1].mx>segtree[pos].mx){ 36 segtree[pos].mx=segtree[pos<<1].mx; 37 segtree[pos].loc=segtree[pos<<1].loc; 38 } 39 if(segtree[pos<<1|1].mx>segtree[pos].mx){ 40 segtree[pos].mx=segtree[pos<<1|1].mx; 41 segtree[pos].loc=segtree[pos<<1|1].loc; 42 } 43 } 44 void build(int pos,int ll,int rr){ 45 if(ll==rr){ 46 segtree[pos].mx=sum[oula[ll]]; 47 segtree[pos].loc=ll; 48 return; 49 } 50 int mid=(ll+rr)>>1; 51 build(pos<<1,ll,mid); 52 build(pos<<1|1,mid+1,rr); 53 up(pos); 54 } 55 void update(int pos,long long dd){//!!!!!!!!!!!!!!!!!!!!!!!! long long 56 segtree[pos].mx-=dd; 57 segtree[pos].tag+=dd; 58 } 59 void down(int pos){ 60 if(!segtree[pos].tag) return; 61 update(pos<<1,segtree[pos].tag); 62 update(pos<<1|1,segtree[pos].tag); 63 segtree[pos].tag=0; 64 return; 65 } 66 void change(int pl,int pr,long long dd,int pos,int ll,int rr){ 67 int mid=(ll+rr)>>1; 68 if(pl>rr||pr<ll) return; 69 if(pl<=ll&&pr>=rr){ 70 update(pos,dd); 71 return; 72 } 73 down(pos); 74 if(pr<=mid) change(pl,pr,dd,pos<<1,ll,mid); 75 else if(pl>mid) change(pl,pr,dd,pos<<1|1,mid+1,rr); 76 else{ 77 change(pl,mid,dd,pos<<1,ll,mid); 78 change(mid+1,pr,dd,pos<<1|1,mid+1,rr); 79 } 80 up(pos); 81 } 82 int main(){ 83 scanf("%d%d",&n,&k); 84 for(int i=1;i<=n;i++) scanf("%lld",&val[i]); 85 int x,y; 86 for(int i=1;i<n;i++){ 87 scanf("%d%d",&x,&y); 88 add(x,y); 89 } 90 sum[1]=val[1]; 91 dfs(1); 92 build(1,1,n); 93 for(int i=1;i<=k;i++){ 94 ans+=segtree[1].mx; 95 for(int j=oula[segtree[1].loc];!check[j]&&j;j=fa[j]){ 96 check[j]=1; 97 change(getin[j],getin[j],inf,1,1,n);//ll的极值??? 98 if(getin[j]<getout[j]) change(getin[j]+1,getout[j],val[j],1,1,n); 99 } 100 } 101 printf("%lld",ans); 102 return 0; 103 }