hdu #5884 Sort(快速哈夫曼树+队列)

来源:互联网 发布:诺基亚6681软件 编辑:程序博客网 时间:2024/05/18 03:43

标签:快速哈夫曼树,队列
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5884
这道题与上一道题十分相似,本质上都是快速哈夫曼树算法,只不过比上一道题稍难一些。
Recently, Bob has just learnt a naive sorting algorithm: merge sort. Now, Bob receives a task from Alice.
Alice will give Bob N sorted sequences, and the i-th sequence includes ai elements. Bob need to merge all of these sequences. He can write a program, which can merge no more than k sequences in one time. The cost of a merging operation is the sum of the length of these sequences. Unfortunately, Alice allows this program to use no more than T cost. So Bob wants to know the smallest k to make the program complete in time.
Input
The first line of input contains an integer t0, the number of test cases. t0 test cases follow.
For each test case, the first line consists two integers N (2N100000) and T (Ni=1ai<T<231).
In the next line there are N integers a1,a2,a3,...,aN(i,0ai1000).
Output
For each test cases, output the smallest k.
题意大概就是,把一个数列以每次最多合并k个数的方式合并起来,直至剩下一个数为止,合并的代价是被合并的数的和,求最小的k使总代价w满足wt
首先很明显,合并数的策略就是选最小的数进行合并,所以我们可以采用与上一题相似的算法,不过只需要开两个队列。设pd(x)表示k取到x时,合并的总代价,那么就有性质pd(a)pd(b)当且仅当ab,所以这道题可以二分。因为求pd(x)代价是O(n),所以总时间复杂度是O(nlogn)
具体过程见代码

#include<cstdio>#include<algorithm>#include<queue>#define maxn 100050typedef long long ll;using namespace std;int t0,n,k,t,a[maxn],l,r,ans,mid,sum[maxn];queue <int> qu1,qu2;bool pd(int k){      while(!qu1.empty()) qu1.pop();      while(!qu2.empty()) qu2.pop();      for(int i=1;i<=n;i++) qu1.push(a[i]);      int num=0;      ll sum=0,ans=0;      if((n-1)%(k-1)!=0){          num=(n-1)%(k-1)+1;          for(int i=1;i<=num;i++) {              sum+=qu1.front();              qu1.pop();          }          qu2.push(sum);          ans+=sum;      }      while(!qu1.empty()){          sum=0;          for(int i=1;i<=k;i++){              if(!qu1.empty() && !qu2.empty() ){                  if(qu1.front()<=qu2.front()){                      sum+=qu1.front();                      qu1.pop();                  } else {                      sum+=qu2.front();                      qu2.pop();                  }              } else if(qu1.empty()){                  sum+=qu2.front();                  qu2.pop();              } else if(qu2.empty()){                  sum+=qu1.front();                  qu1.pop();              }          }          ans+=sum;          qu2.push(sum);      }      if(ans>t) return false;      sum=0;num=0;      while(!qu2.empty()){          sum+=qu2.front();          qu2.pop();          num++;          if(num==k){              qu2.push(sum);              ans+=sum;              sum=0;              num=0;              if(qu2.size()==1) break;          }      }      if(ans>t) return false;      return true;  }  int main(){    int i,j;    scanf("%d",&t0);    while (t0--)    {        scanf("%d%d",&n,&t);        for (i=1;i<=n;i++) scanf("%d",&a[i]);         sort(a+1,a+n+1);         l=2; r=n; ans=1; sum[0]=0;        for (i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];        while (l<=r)        {            mid=(l+r)/2;            if (pd(mid))            {                r=mid-1; ans=mid;            }            else l=mid+1;        }        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击