• 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
  • 相关阅读:
    IOI 1996 网络协议
    lougu P2344奶牛抗议
    Poj3764 The XOR-longest Path
    A Simple Problem with Integers (线段树)
    NOIP2011 选择客栈
    20181029 T3 乐谱分段
    20181029 T2 寻宝游戏
    20181029 T1 教科书般的亵渎
    NOIP2011聪明的质监员
    浅谈AC自动机
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5886592.html
Copyright © 2020-2023  润新知