codeforces Good Bye 2015 E. 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.

Examples
input
5
10 20 30
1 1 1 1 50
output

2

题意:有三个火枪手,每个人都有一定的攻击力,下面有N只怪物,每只怪物都有一定的防御力,问至少要经过多少回合之后才能把所有的怪物都打死(每个回合每个火枪手都只能打一次,如果某只怪物的抵抗力之和大于这三个火枪手的攻击力之和,则直接输出-1.

分析:

首先,我们先对火枪手的攻击力和怪物的抵抗力按从小到大排序,火枪手的攻击力记为w[0],w[1],w[2]

如果某些怪物的抵抗力大于w[1]+w[2],则一定要三个火枪手在同一回合之内攻击他,

如果某些怪物的抵抗力大于w[0]+w[2],则要攻击力大的两个火枪手在同一回合之内攻击他,另一个火枪手可以选择他所能杀死的怪物的抵抗力的最大值去攻击

如果某些怪物的抵抗力大于w[0]+w[1],则要攻击力分别为最大和最小的的两个火枪手在同一回合之内攻击他,另一个火枪手可以选择他所能杀死的怪物的抵抗力的最大值去攻击

这三种情况排除之后,便只会有两种情况,一种是w[0]w[1]同时使用,w[2]另外使用,第二种情况是三个火枪手都分别使用,

假设现在w[0]w[1]同时使用可以杀死的怪为num1,w[2]可以杀死的怪为num2,(假设num1>num2)这样所以要进行的回合数便为

if(num1>=2*num2)

        return num1-num2;

    else

        return num1-num2+(2*num2-num1+1)/2;

所以我们只需要枚举三个火枪手分开使用的回合数是多少

#include<bits/stdc++.h>
using namespace std;
const int INF=1e9;
multiset<int>st;
const int maxn=201000;
int w[3],a[maxn];
int ans=0;
multiset<int>::iterator it;
int num1,num2,C1,C2;

void solve(int num1,int num2){//大于等于num1,小于num2
    while(st.size()!=0){
        it=st.lower_bound(num1);//查找大于等于这个数的
        if(it==st.end())
            break;
        st.erase(it);
        ans++;
        it=st.lower_bound(num2);
        if(it==st.end())
            it--;
        if(num2>=(*it))
            st.erase(it);
        else if(it!=st.begin()){
            it--;
            st.erase(it);
        }
    }
}

void Change(int num){
    if(st.size()!=0){
        it=st.lower_bound(num);//查找大于等于这个数的
        if(it==st.end())
            it--;
        if((*it)>num){
            if(it==st.begin())
                return ;
            else{
                it--;
                if((*it)<=C1)
                    num1--;
                if((*it)<=C2)
                    num2--;
                st.erase(it);
            }
        }
        else{
            if((*it)<=C1)
                num1--;
            if((*it)<=C2)
                num2--;
            st.erase(it);
        }
    }
}

int R(){
    if(num1>=2*num2)
        return num1-num2;
    else
        return num1-num2+(2*num2-num1+1)/2;
}

int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<=2;i++)
        scanf("%d",&w[i]);
    sort(w,w+3);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        st.insert(a[i]);
    }
    sort(a+1,a+n+1);
//    for(int i=1;i<=n;i++)
//        printf("PPP%d\n",a[i]);
    if(a[n]>w[0]+w[1]+w[2]){
        printf("-1\n");
        return 0;
    }
    solve(w[1]+w[2]+1,0);
    solve(w[0]+w[2]+1,w[0]);
    solve(max(w[0]+w[1],w[2])+1,w[1]);
    num1=0,num2=0,C1=w[0]+w[1],C2=w[2];
    //cout<<st.size()<<endl;
    it=st.begin();
    while(it!=st.end()){
        if((*it)<=C1)
            num1++;
        if((*it)<=C2)
            num2++;
        it++;
    }
    if(C1<C2){
        swap(C1,C2);
        swap(num1,num2);
    }
    int add=R();
    for(int i=1;i<=n;i++){  //枚举a,b,c分开使用了多少次
        Change(w[0]);
        Change(w[1]);
        Change(w[2]);
        add=min(add,i+R());
    }
    printf("%d\n",add+ans);
    return 0;
}

你可能感兴趣的:(codeforces Good Bye 2015 E. New Year and Three Musketeers)