zoukankan      html  css  js  c++  java
  • HDU 5884 Sort

    二分,验证。

    二分$k$,然后进行验证。有一个地方需要注意一下:如果$n$个数,每次合并$k$个,最后一次不能合$k$个,那么一开始需要补$0$之后再合并才是最优的。合并的时候用优先队列合并时间复杂度过高,可以用两个队列模拟一下,优化掉一个$log$。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-6;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x)
    {
        char c=getchar(); x=0;
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) {x=x*10+c-'0'; c=getchar();}
    }
    
    const int maxn=100010;
    int n,T,k,a[maxn];
    
    bool check(int x)
    {
        queue<LL>Q[2];
        for(int i=1;i<=n;i++) Q[0].push(a[i]);
    
        int sz=n; LL sum=0,m0=a[n],m1=0;
    
        if(n%(k-1)==1){}
        else
        {
            int num; if(n%(x-1)==0) num=x-1; else num=n%(x-1);
    
            LL c=0;
            for(int i=1;i<=num;i++)
            {
                c=c+Q[0].front(); Q[0].pop();
            }
    
            sum=sum+c;
            if(sum>k) return 0;
    
            Q[1].push(c); m1=c;
    
            sz=sz-num+1;
        }
    
        if(sz==1)
        {
            if(sum>k) return 0;
            return 1;
        }
    
        while(1)
        {
            LL c=0;
            for(int i=1;i<=min(sz,x);i++)
            {
                if((!Q[0].empty())&&(!Q[1].empty()))
                {
                    if(Q[0].front()<Q[1].front()) { c=c+Q[0].front(); Q[0].pop(); }
                    else { c=c+Q[1].front(); Q[1].pop(); }
                }
                else if(!Q[0].empty()) { c=c+Q[0].front(); Q[0].pop(); }
                else { c=c+Q[1].front(); Q[1].pop(); }
            }
    
            sum=sum+c;
            if(sum>k) return 0;
    
            if(Q[0].empty()) { Q[0].push(c); m0=c; }
            else if(Q[1].empty()) { Q[1].push(c); m1=c; }
            else
            {
                if(c>=m0) { Q[0].push(c); m0=c; }
                else if(c>=m1) { Q[1].push(c); m1=c; }
            }
    
            if(sz<=x) break;
    
            sz=sz-x+1;
        }
    
        if(sum>k) return 0;
        return 1;
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            sort(a+1,a+1+n);
            int L=2,R=n,ans;
            while(L<=R)
            {
                int m=(L+R)/2;
                if(check(m)) ans=m,R=m-1;
                else L=m+1;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    java设计模式-代理模式
    java设计模式-适配器模式
    java设计模式-策略模式
    java设计模式-建造者模式
    HTML table 边框双线变单线
    flutter flutter_cupertino_date_picker 时间插件的用法
    flutter TextField 输入框被软键盘挡住的解决方案
    vue 多层组件相互嵌套的时候 数据源更新 dom没更新 彻底清除组件缓存
    elementUI 上传文件图片大小加了限制后 仍然上传了
    elementUI el-date-picker 时间范围设置 固定时间段可选 配置
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5886993.html
Copyright © 2011-2022 走看看