BZOJ 2809 [Apio2012]dispatching

【题解】

  贪心地选择子树内的节点,优先选代价小的。如果当前费用超出限制了就依次去掉当前费用最大的点,直到费用不超过限制。每个点的情况由它的孩子合并得到,所以要用到可并堆(左偏树)。

  

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define LL long long
 4 #define rg register
 5 #define N 200010
 6 using namespace std;
 7 int tot,root,last[N],c[N][2],rt[N],size[N];
 8 LL n,m,sum[N],val[N],l[N],ans=0;
 9 struct edge{
10     int to,pre;
11 }e[N];
12 inline LL read(){
13     LL k=0,f=1; char c=getchar();
14     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
15     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
16     return k*f;
17 }
18 inline LL max(LL x,LL y){return x>y?x:y;}
19 inline void update(int x){
20     size[x]=size[c[x][0]]+size[c[x][1]]+1;
21     sum[x]=sum[c[x][0]]+sum[c[x][1]]+val[x];
22 }
23 inline int merge(int x,int y){
24     if(!x||!y) return x+y; if(val[x]<val[y]) swap(x,y);
25     c[x][1]=merge(c[x][1],y); swap(c[x][0],c[x][1]);
26     update(x); return x;
27 }
28 inline void pop(int &x){
29     int tmp=merge(c[x][0],c[x][1]);
30     c[x][0]=c[x][1]=0; size[x]=1; sum[x]=val[x]; x=tmp;
31 }
32 void dfs(int x){
33     rt[x]=x;
34     for(rg int i=last[x],to;i;i=e[i].pre) dfs(to=e[i].to),rt[x]=merge(rt[x],rt[to]);
35     while(size[rt[x]]&&sum[rt[x]]>m) pop(rt[x]);
36     ans=max(ans,1ll*size[rt[x]]*l[x]);
37 }
38 int main(){
39     n=read(); m=read();
40     for(rg int i=1;i<=n;i++){
41         LL x=read(),y=read(),z=read();
42         val[i]=sum[i]=y; l[i]=z; size[i]=1;
43         if(x) e[++tot]=(edge){i,last[x]},last[x]=tot; else root=i;
44     }
45     dfs(root);
46     printf("%lld\n",ans);
47     return 0;
48 }
View Code

 

posted @ 2018-04-11 21:09  Driver_Lao  阅读(132)  评论(0编辑  收藏  举报