zoukankan      html  css  js  c++  java
  • Gym 101194D / UVALive 7900

    题目链接:

    http://codeforces.com/gym/101194/attachments

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5922

    题意:

    给出 $N$ 个冰淇淋球,第 $i$ 个冰淇淋球大小为 $B_i$,现在已知冰淇淋球堆叠起来可组成一个冰淇淋。

    对于上下相邻的两个冰淇淋球,只有上面的那个大小不超过下面的那个的一般,才能堆叠起来。

    现在已知 $K$ 个冰淇淋球可以组成一个冰淇淋,问给出的 $N$ 个冰淇淋球最多能组成多少个冰淇淋。

    假的题解:

    比赛的时候想的一个(假的)贪心思路:

      从最大的冰淇淋球开始贪心,对于目前这个球,始终选择小于等于当前球体积的一半中体积最大的冰淇淋球。

    进而可得这样一个用队列维护 $O(N)$ 的做法:

      从大到小枚举冰淇淋球,用一个队列维护:目前产生的冰淇淋的最上端的那个冰淇淋球,以及该冰淇淋包含的冰淇淋球数目。

      枚举到当前这个球 $B_i$,与队首冰淇淋进行比较,若可以放到这个冰淇淋上,就放上去产生一个新的冰淇淋,出队队首元素,入队一个新冰淇淋;否则就作为一个新的冰淇淋入队。

    代码(AC on UVALive 7900, WA on Gym 101194D):

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,int> pli;
    const int maxn=3e5+10;
    
    int n,k;
    ll b[maxn];
    queue<pli> Q;
    
    int main()
    {
        int T;
        cin>>T;
        for(int kase=1;kase<=T;kase++)
        {
            cin>>n>>k;
            for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
            sort(b+1,b+n+1);
            int ans=0;
            while(!Q.empty()) Q.pop();
            for(int i=n;i>=1;i--)
            {
                if(Q.empty())
                {
                    Q.push(make_pair(b[i],1));
                    continue;
                }
                pli now=Q.front();
                if(b[i]<=(now.first>>1))
                {
                    Q.pop();
                    if(now.second+1>=k) ans++;
                    else Q.push(make_pair(b[i],now.second+1));
                }
                else Q.push(make_pair(b[i],1));
            }
            printf("Case #%d: %d
    ",kase,ans);
        }
    }

    真的题解:

    若要求做 $cnt$ 个冰淇淋,那么肯定先取最小的 $cnt$ 个冰淇淋球作为顶,然后一点点往前后推判断是否真的能做出 $cnt$ 个球。

    那么,就可以二分答案,最少 $0$ 个冰淇淋,最多 $left lfloor frac{N}{K} ight floor$ 个冰淇淋。

    时间复杂度 $O(N log left lfloor frac{N}{K} ight floor)$

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,int> pli;
    const int maxn=3e5+10;
    
    int n,k;
    ll b[maxn];
    queue<pli> Q;
    inline bool judge(int cnt)
    {
        for(int i=1;i<=cnt;i++) Q.push(make_pair(b[i],1));
        for(int i=cnt+1;i<=n;i++)
        {
            pli now=Q.front();
            if(b[i]>=(now.first<<1))
            {
                Q.pop();
                Q.push(make_pair(b[i],now.second+1));
            }
        }
        int res=0;
        while(!Q.empty())
        {
            res+=(Q.front().second>=k);
            Q.pop();
        }
        return res>=cnt;
    }
    
    int main()
    {
        int T;
        cin>>T;
        for(int kase=1;kase<=T;kase++)
        {
            cin>>n>>k;
            for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
            sort(b+1,b+n+1);
            int l=0, r=n/k;
            while(l<r)
            {
                int mid=(l+r+1)>>1;
                if(judge(mid)) l=mid;
                else r=mid-1;
            }
            printf("Case #%d: %d
    ",kase,l);
        }
    }
  • 相关阅读:
    synchronized内置锁
    《JavaScript闯关记》视频版硬广
    想提高团队技术,来试试这个套路!
    从国企到阿里的面试经历(二)
    从国企到阿里的面试经历(一)
    《JavaScript 闯关记》之垃圾回收和内存管理
    《JavaScript 闯关记》之原型及原型链
    《JavaScript 闯关记》之作用域和闭包
    如何排版 微信公众号「代码块」之 MarkEditor
    《JavaScript 闯关记》之事件
  • 原文地址:https://www.cnblogs.com/dilthey/p/9903768.html
Copyright © 2011-2022 走看看