HDU 5884 (贪心)

problem sort

题目大意

  有n个数组,每个数组有a[i]个元素,每次可以将至多k个数组合并为一个数组,所花费代价为这些数组的元素和。给定代价上限,求将所有数组合并为1个数组的最小k。

解题分析  

  二分k后就成了k叉哈夫曼树问题。

  对于k叉哈夫曼树,可以利用所合并元素的权值单调性,用两个双端队列来实现。

  另外,如果(n-1)%(k-1) != 0 , 则需要另外在补上(k-1) - (n-1)%(k-1)个0。

参考程序

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <string>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <cassert>
 13 #include <iostream>
 14 #include <algorithm>
 15 #pragma comment(linker,"/STACK:102400000,102400000")
 16 using namespace std;
 17 
 18 #define N 100008            
 19 #define M 50008    
 20 #define LL long long
 21 #define lson l,m,rt<<1
 22 #define rson m+1,r,rt<<1|1 
 23 #define clr(x,v) memset(x,v,sizeof(x));
 24 #define bitcnt(x) __builtin_popcount(x)
 25 #define rep(x,y,z) for (int x=y;x<=z;x++)
 26 #define repd(x,y,z) for (int x=y;x>=z;x--)
 27 const int mo  = 1000000007;
 28 const int inf = 0x3f3f3f3f;
 29 const int INF = 2000000000;
 30 /**************************************************************************/ 
 31 
 32 int T;
 33 int n,limit;
 34 int a[N*10],b[N*10],c[N*10];
 35 
 36 int check(int k)
 37 {
 38     //printf("%d
",k );
 39     int tmp=((k-1)-(n-1) % (k-1)) % (k-1);
 40     int m=n+tmp;
 41     rep(i,1,tmp) b[i]=0;
 42     rep(i,tmp+1,m) b[i]=a[i-tmp];
 43     LL s=0;
 44     int i=1,l=1,r=0,op=0,sum=0;
 45     while (i<=m)
 46     {
 47         if (l>r || b[i]<=c[l])
 48         {
 49             op++;
 50             sum+=b[i];
 51             i++;
 52         }
 53         else
 54         {
 55             op++;
 56             sum+=c[l];
 57             l++;
 58         }
 59         if (op==k)
 60         {
 61             s+=sum;
 62             c[++r]=sum;
 63             op=sum=0;
 64         }
 65     }
 66     while (l<=r)
 67     {
 68         op++;
 69         sum+=c[l];
 70         l++;
 71         if (op==k)
 72         {
 73             s+=sum;
 74             c[++r]=sum;
 75             op=sum=0;
 76         }    
 77     }
 78     //rep(i,1,m)  printf("%d ",b[i]); printf("
");
 79     //rep(i,1,r)  printf("%d ",c[i]); printf("
");
 80     if (op!=1) s+=sum;
 81     //printf("%lld
",s );
 82     return s<=limit;
 83 }
 84 
 85 int cmp(int x,int y)
 86 {
 87     return x>y;
 88 }
 89 int main()
 90 {
 91     scanf("%d",&T);
 92     while (T--)
 93     {
 94         scanf("%d%d",&n,&limit);
 95         rep(i,1,n) scanf("%d",&a[i]);
 96         sort(a+1,a+n+1);
 97         int l=2,r=n,mid,res;
 98         while (l<=r)
 99         {
100             mid=(l+r)/2;
101             if (check(mid))
102             {
103                 res=mid;
104                 r=mid-1;
105             }
106             else l=mid+1;
107         }
108         printf("%d
",res);
109     }
110 }
View Code
原文地址:https://www.cnblogs.com/rpSebastian/p/5886592.html