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 }