【BZOJ】【2809】【APIO2012】派遣dispatching

贪心/可并堆


  跪了……我这么弱果然还是应该回家种红薯去……

  考虑选人的时候,每个人对答案的贡献其实是一样的,都是1,那么我们就贪心地去选花钱少的就好啦~

  具体的做法:倒着枚举(因为有b[i]<i),考虑选第 i 个人做领导者的时候,以他为根的子树中如果花费>m,那么我们就踢掉花钱最多的人,直到sum<m,用l[i]*num[i]更新答案(num[i]表示以 i 为根的子树中选了多少人),然后把这棵子树的堆并到他的父亲的堆中去(初始每个人的堆都只有他自己)

  或许你看看代码更容易理解一点……

  总之就是枚举领导者,属下能多选就多选,不能选的时候踢掉花钱最多的那个

  当然这题只要是支持快速合并以及删除最大值的数据结构都可以的……比如用splay/treap+启发式合并也可以捉,嗯我写的是左偏树……

 1 /**************************************************************
 2     Problem: 2809
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:948 ms
 7     Memory:7528 kb
 8 ****************************************************************/
 9  
10 //BZOJ 2809
11 #include<vector>
12 #include<cstdio>
13 #include<cstring>
14 #include<cstdlib>
15 #include<iostream>
16 #include<algorithm>
17 #define rep(i,n) for(int i=0;i<n;++i)
18 #define F(i,j,n) for(int i=j;i<=n;++i)
19 #define D(i,j,n) for(int i=j;i>=n;--i)
20 #define pb push_back
21 using namespace std;
22 inline int getint(){
23     int v=0,sign=1; char ch=getchar();
24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
26     return v*sign;
27 }
28 const int N=100010,INF=~0u>>2;
29 typedef long long LL;
30 /******************tamplate*********************/
31 LL n,m,b[N],c[N],l[N],rt[N];
32 LL ans=0;
33 struct node{
34     int v,l,r,dis,f,num; LL sum;
35     node(int v=0,int l=0,int r=0,int dis=0,
36          int f=0,int num=0,LL sum=0):
37         v(v),l(l),r(r),dis(dis),
38         f(f),num(num),sum(sum){}
39 };
40 struct Left_tree{
41     node t[N];
42     int merge(int x,int y){
43         if(!x||!y) return x?x:y;
44         if (t[x].v<t[y].v) swap(x,y);
45         t[x].r=merge(t[x].r,y);
46 //      t[t[x].r].f=x;
47         if (t[t[x].l].dis<t[t[x].r].dis) swap(t[x].l,t[x].r);
48         if (t[x].r==0) t[x].dis=0;
49         else t[x].dis=t[t[x].r].dis+1;
50         t[x].sum=t[t[x].l].sum+t[t[x].r].sum+t[x].v;
51         t[x].num=t[t[x].l].num+t[t[x].r].num+1;
52         return x;
53     }
54     int pop(int x){
55         int l=t[x].l,r=t[x].r;
56 //      t[l].f=l; t[r].f=r;
57         t[x].l=t[x].r=t[x].dis=0;
58         return merge(l,r);
59     }
60     void init(){
61         n=getint();m=getint();
62         F(i,1,n){
63             b[i]=getint();
64             t[i].sum=t[i].v=getint();
65             l[i]=getint();
66  
67             t[i].num=1;
68             rt[i]=i;
69         }
70         D(i,n,1){
71             while(t[rt[i]].sum>m) rt[i]=pop(rt[i]);
72             if (t[rt[i]].num*l[i]>ans) ans=t[rt[i]].num*l[i];
73             if (rt[i] && b[i]) rt[b[i]]=merge(rt[b[i]],rt[i]);
74         }
75         printf("%lld\n",ans);
76     }
77 }H;
78 int main(){
79 #ifndef ONLINE_JUDGE
80     freopen("2809.in","r",stdin);
81     freopen("2809.out","w",stdout);
82 #endif
83     H.init();
84     return 0;
85 }
View Code

 

posted @ 2015-03-27 13:02  Tunix  阅读(292)  评论(0编辑  收藏  举报