[51nod1474]宝藏图

  有n堆宝藏,每一堆宝藏有一个挖掘所需要的时间ti,有一个价值qi。

  现在是做一个宝藏图。这个宝藏图是这样的,宝藏图的形状是一棵二叉树,二叉树刚好有k个叶子结点,从n堆宝藏中选k堆放到二叉树的叶子结点上,每个叶子结点只能放一堆宝藏,每堆宝藏只能放到一个叶子结点上。然后派k个人去找宝藏,每个人会分配到一个宝藏供他查找,在这k个宝藏中,每一个宝藏都会被分配给某一个人,k个人从根结点出发,每个人从当前结点往相邻结点走的时候要花费一个单位的时间,到达他指定的宝藏的时候,他要花费那个宝藏所需要的挖掘时间去挖掘那个宝藏,然后他获得那个宝藏的时间就是他行走的时间+挖掘时间。但是大家必须在T的时间内得到宝藏,所以现在要求在大家能在T时间内得到宝藏的情况下,使得宝藏的总价值最大。

  注意:可以不经过任何中间结点直接到达宝藏进行挖掘(样例二)。

 Input
  单组测试数据。
  第一行包含两个整数n 和T (1 ≤ n,T ≤ 100000),表示宝藏的数目和时间限制。
  接下来n行,每行有两个整数ti, qi (1 ≤ ti ≤ T, 1 ≤ qi ≤ 1000),第i个宝藏的挖掘时间和它的价值。
 Output
  输出最大的宝藏总价值。

 

 

  连暴力都不会写系列。

  cf官网给出了O(n^2T)的做法。。。从底往上一层一层算,f[h][w]表示第h层,这层已确定要有w个节点。

  每次枚举这一层有x个叶子节点,就能从f[h][w]转移到f[h-1][(w+x+1)/2]...

  之后看了cf上别人的AC代码。。在同一层里直接贪心把相邻最大的连向同个父亲就好了.....

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cmath>
 7 #include<cstdlib>
 8 #define ll long long
 9 #define ull unsigned long long
10 #define ui unsigned int
11 #define d double
12 #define ld long double
13 using namespace std;
14 const int maxn=100233,modd=1000000007;
15 struct zs{int t,v;}a[maxn];
16 int mp[2][maxn],num[2];
17 int i,j,k,n,m;
18 
19 
20 int ra,fh;char rx;
21 inline int read(){
22     rx=getchar(),ra=0,fh=1;
23     while(rx<'0'&&rx!='-')rx=getchar();
24     if(rx=='-')fh=-1,rx=getchar();
25     while(rx>='0')ra=ra*10+rx-48,rx=getchar();return ra*fh;
26 }
27 
28 bool operator <(zs a,zs b){return a.t<b.t;}
29 bool cmp(int a,int b){return a>b;}
30 int main(){
31     int n=read(),T=read();register int i,j;
32     for(i=1;i<=n;i++)a[i].t=read(),a[i].v=read();
33     sort(a+1,a+1+n);int top=1;bool now=1,pre=0;
34     
35     
36     for(i=1;i<=T;i++,now^=1,pre^=1){
37         while(top<=n&&a[top].t==i)mp[pre][++num[pre]]=a[top++].v;
38         sort(mp[pre]+1,mp[pre]+1+num[pre],cmp);
39 //            for(j=1;j<=num[pre];j++)printf("%d  ",mp[pre][j]);puts("");
40         if(i==T)return printf("%d\n",mp[pre][1]),0;
41         if(num[pre]&1)mp[pre][++num[pre]]=0;
42         
43         for(j=1,num[now]=0;j<num[pre];j+=2)mp[now][++num[now]]=mp[pre][j]+mp[pre][j+1];
44     }
45 }
View Code

 

posted @ 2016-10-12 14:31  czllgzmzl  阅读(418)  评论(0编辑  收藏  举报