CodeForces 611E New Year and Three Musketeers

E. New Year and Three Musketeers
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Do you know the story about the three musketeers? Anyway, you must help them now.

Richelimakieu is a cardinal in the city of Bearis. He found three brave warriors and called them the three musketeers. Athos has strengtha, Borthos strength b, and Caramis has strength c.

The year 2015 is almost over and there are still n criminals to be defeated. The i-th criminal has strength ti. It's hard to defeat strong criminals — maybe musketeers will have to fight together to achieve it.

Richelimakieu will coordinate musketeers' actions. In each hour each musketeer can either do nothing or be assigned to one criminal. Two or three musketeers can be assigned to the same criminal and then their strengths are summed up. A criminal can be defeated in exactly one hour (also if two or three musketeers fight him). Richelimakieu can't allow the situation where a criminal has strength bigger than the sum of strengths of musketeers fighting him — a criminal would win then!

In other words, there are three ways to defeat a criminal.

  • A musketeer of the strength x in one hour can defeat a criminal of the strength not greater than x. So, for example Athos in one hour can defeat criminal i only if ti ≤ a.
  • Two musketeers can fight together and in one hour defeat a criminal of the strength not greater than the sum of strengths of these two musketeers. So, for example Athos and Caramis in one hour can defeat criminal i only if ti ≤ a + c. Note that the third remaining musketeer can either do nothing or fight some other criminal.
  • Similarly, all three musketeers can fight together and in one hour defeat a criminal of the strength not greater than the sum of musketeers' strengths, i.e. ti ≤ a + b + c.

Richelimakieu doesn't want musketeers to fight during the New Year's Eve. Thus, he must coordinate their actions in order to minimize the number of hours till all criminals will be defeated.

Find the minimum number of hours to defeat all criminals. If musketeers can't defeat them all then print "-1" (without the quotes) instead.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 200 000) — the number of criminals.

The second line contains three integers ab and c (1 ≤ a, b, c ≤ 108) — strengths of musketeers.

The third line contains n integers t1, t2, ..., tn (1 ≤ ti ≤ 108) — strengths of criminals.

Output

Print one line with the answer.

If it's impossible to defeat all criminals, print "-1" (without the quotes). Otherwise, print the minimum number of hours the three musketeers will spend on defeating all criminals.

Sample test(s)
input
5
10 20 30
1 1 1 1 50
output
2
input
5
10 20 30
1 1 1 1 51
output
3
input
7
30 20 10
34 19 50 33 88 15 20
output
-1
input
6
10 5 10
10 9 5 25 20 5
output
3
Note

In the first sample Athos has strength 10, Borthos 20, and Caramis 30. They can defeat all criminals in two hours:

  • Borthos and Caramis should together fight a criminal with strength 50. In the same hour Athos can fight one of four criminals with strength 1.
  • There are three criminals left, each with strength 1. Each musketeer can fight one criminal in the second hour.

In the second sample all three musketeers must together fight a criminal with strength 51. It takes one hour. In the second hour they can fight separately, each with one criminal. In the third hour one criminal is left and any of musketeers can fight him.


其实做这题时,很渣的我其实是很崩溃的,开始写了之后发现WA然后好不容易找到bug之后改了之后然后又TLE不得不说我很无奈啊,然后找人家的题解,发现人家用二分做。。。然后我就默默的看然后重新写。。。二分查找范围是n/3~n这个都知道,然后就是判断的时候,尽量找能力低的不超给定时间的做,然后两个人或三个人合作的次数也不能超给定时间。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 400000
using namespace std;
int n,a,b,c,num[maxn];
void rswap(int &a,int &b)
{
    a=a^b;
    b=b^a;
    a=a^b;
}
int judge(int cnt)
{
    int aa=0,bb=0,cc=0,s=0;
    for(int i=n-1;i>=0;--i)
    {
        if(num[i]<=c)
        {
            if(cc<cnt)
                cc++;
            else if(bb<cnt)
                bb++;
            else if(aa<cnt)
                aa++;
            else
                return 0;
        }
        else if(num[i]<=b)
        {
            if(bb<cnt)
                bb++;
            else if(aa<cnt)
                aa++;
            else
                return 0;
        }
        else if(num[i]<=a)
        {
            if(aa<cnt)
                aa++;
            else if(num[i]<=b+c&&bb<cnt&&cc<cnt)
                bb++,cc++,s++;
            else
                return 0;
        }
        else if(num[i]<=b+c)
        {
            if(bb<cnt&&cc<cnt)
                bb++,cc++,s++;
            else if(aa<cnt&&cc<cnt)
                aa++,cc++,s++;
            else if(aa<cnt&&bb<cnt)
                aa++,bb++,s++;
            else
                return 0;
        }
        else if(num[i]<=a+c)
        {
            if(aa<cnt&&cc<cnt)
                aa++,cc++,s++;
            else if(aa<cnt&&bb<cnt)
                aa++,bb++,s++;
            else
                return 0;
        }
        else if(num[i]<=a+b)
        {
            if(aa<cnt&&bb<cnt)
                aa++,bb++,s++;
            else
                return 0;
        }
        else if(num[i]<=a+b+c)
        {
            if(aa<cnt&&bb<cnt&&cc<cnt)
                aa++,bb++,cc++,s++;
            else
                return 0;
        }
        //printf("i=%d aa=%d bb=%d cc=%d\n",i,aa,bb,cc);
    }
    if(s>cnt)
        return 0;
    return 1;
}
int bsearch(int l,int r)
{
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(!judge(mid))
            l=mid+1;
        else
            r=mid-1;
    }
    return l;
}
int main()
{
    while(~scanf("%d",&n))
    {
        scanf("%d%d%d",&a,&b,&c);
        if(a<b)
            rswap(a,b);
        if(a<c)
            rswap(a,c);
        if(b<c)
            rswap(b,c);
        for(int i=0;i<n;++i)
            scanf("%d",&num[i]);
        sort(num,num+n);
        if(num[n-1]>a+b+c)
        {
            printf("-1\n");
            continue;
        }
        if(num[n-1]<=c)
        {
            if(n%3==0)
                printf("%d\n",n/3);
            else
                printf("%d\n",n/3+1);
            continue;
        }
        printf("%d\n",bsearch(n/3,n));
    }
    return 0;
}


我写了好久反复修改的超时代码。。。(真是丢人)

//当aa很大时,可能a能处理的可以找b+c代替
//TLE
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200200
using namespace std;
int rec[maxn];
bool vis[maxn];
void sw(int &a,int &b)
{
    a=a^b;
    b=b^a;
    a=a^b;
}
int main()
{
    int n,a,b,c;
    while(~scanf("%d",&n))
    {
        int aa=0,bb=0,cc=0;
        scanf("%d%d%d",&a,&b,&c);
        if(a<b)
            sw(a,b);
        if(a<c)
            sw(a,c);
        if(b<c)
            sw(b,c);
        for(int i=0;i<n;++i)
            scanf("%d",&rec[i]);
        sort(rec,rec+n);
        memset(vis,false,sizeof(vis));
        if(rec[n-1]>a+b+c)
        {
            printf("-1\n");
            continue;
        }
        if(rec[n-1]<=c)
        {
            if(n%3==0)
                printf("%d\n",n/3);
            else
                printf("%d\n",n/3+1);
            continue;
        }
        int t=0,i;
        for(i=0;i<n;++i)
            if(rec[i]>a)
                break;
        while(i<n)
        {
            vis[i]=true;
            if(rec[i]<=b+c)
            {
                for(int j=i-1;j>=0;--j)
                {
                    if(!vis[j]&&rec[j]<=a)
                    {
                        vis[j]=true;
                        break;
                    }
                }
            }
            else if(rec[i]<=a+c)
            {
                for(int j=i-1;j>=0;--j)
                {
                    if(!vis[j]&&rec[j]<=b)
                    {
                        vis[j]=true;
                        break;
                    }
                }
            }
            else if(rec[i]<=a+b)
            {
                for(int j=i-1;j>=0;--j)
                {
                    if(!vis[j]&&rec[j]<=c)
                    {
                        vis[j]=true;
                        break;
                    }
                }
            }
            t++;
            i++;
        }
        for(i=n-1;i>=0;--i)
        {
            if(!vis[i])
            {
                int flagb=0,flagc=0;
                if(rec[i]<=a)
                {
                    vis[i]=true;
                    for(int j=i-1;j>=0;--j)
                    {
                        if(!vis[j]&&!flagb&&rec[j]<=b)
                        {
                            flagb=1;
                            vis[j]=true;
                        }
                        if(!vis[j]&&!flagc&&rec[j]<=c)
                        {
                            flagc=1;
                            vis[j]=true;
                            break;
                        }
                    }
                    if(!flagc&&!flagb)
                    {
                        for(int j=i-1;j>=0;--j)
                        {
                            if(!vis[j]&&rec[j]<=b+c)
                            {
                                vis[j]=true;
                                break;
                            }
                        }
                    }
                }
                t++;
            }
        }
        printf("%d\n",t);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值