zoukankan      html  css  js  c++  java
  • hdu_5884_Sort(二分+单调队列)

    题目链接:hdu_5884_Sort

    题意:

    有n个数,每个数有个值,现在你可以选择每次K个数合并,合并的消耗为这K个数的权值和,问在合并为只有1个数的时候,总消耗不超过T的情况下,最小的K是多少

    题解:

    首先要选满足条件的最小K,肯定会想到二分。

    然后是如何来写这个check函数的问题

    我们要贪心做到使消耗最小,首先我们将所有的数排序

    然后对于每次的check的mid都取最小的mid个数来合并,然后把新产生的数扔进优先队列,直到最后只剩一个数。

    不过这样的做法是n*(logn)2 ,常数写的小,带优化能卡过去,不过我反正卡不过去,然后就需要一个数据结构优化一个log

    那就是用单调队列,可以先看看这篇文章  合并果子

    然而这里有个小细节,不注意是过不去的:

    对于n个数,一共要合并n-1个数,才能最后剩一个数,然后对于每次的mid,每次会合并mid-1个数,如果(n-1)%(mid-1)!=0,那么我们得先取(n-1)%(mid-1)+1个数来合并,这样后面合并的时候才能刚合适,如果不取,读者可以自己模拟一下,会出错。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;++i)
     3 using namespace std;
     4 typedef long long ll;
     5 
     6 const int N=1e5+7;
     7 int t,n,T,a[N];
     8 ll inf=1e18;
     9 queue<ll>Q1,Q2;
    10 
    11 bool check(int mid)
    12 {
    13     ll ans=0;
    14     while(!Q1.empty())Q1.pop();
    15     while(!Q2.empty())Q2.pop();
    16     F(i,1,n)Q1.push(a[i]);
    17     int num=(n-1)%(mid-1);
    18     if(num)
    19     {
    20         ll tp=0;
    21         F(i,1,num+1)tp+=Q1.front(),Q1.pop();
    22         ans+=tp;
    23         Q2.push(tp);
    24     }
    25     while(1)
    26     {
    27         ll tp=0;
    28         F(i,1,mid)
    29         {
    30             ll x=inf,y=inf;
    31             if(Q1.empty()&&Q2.empty())break;
    32             if(!Q1.empty())x=Q1.front();
    33             if(!Q2.empty())y=Q2.front();
    34             if(x<y)tp+=x,Q1.pop();
    35             else tp+=y,Q2.pop();
    36         }
    37         ans+=tp;
    38         if(ans>T)return 0;
    39         if(Q1.empty()&&Q2.empty())break;
    40         Q2.push(tp);
    41     }
    42     return ans<=T;
    43 }
    44 
    45 
    46 int main(){
    47     scanf("%d",&t);
    48     while(t--)
    49     {
    50         scanf("%d%d",&n,&T);
    51         F(i,1,n)scanf("%d",a+i);
    52         sort(a+1,a+1+n);
    53         int l=2,r=n,mid,ans;
    54         while(l<=r)mid=(l+r)>>1,check(mid)?r=mid-1,ans=mid:l=mid+1;
    55         printf("%d
    ",ans);
    56     }
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    第六周学习总结
    20165227 《Java程序设计》实验一(Java开发环境的熟悉)实验报告
    第五周学习总结
    20165227 20165228结对学习感想
    第四周课堂测试补做
    第四周作业
    20165227第三周学习总结
    第二周学习总结
    20165304《JAVA程序设计》第四周学习总结
    20165304 2017-2018-2 《Java程序设计》第3周学习总结
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5887144.html
Copyright © 2011-2022 走看看