Fountains CodeForces - 799C

  取得2个物品有3种情况:1.选一个c类型,一个d类型  2.选2个c类型  3.选2个d类型,分类讨论一下

  写了这题才发现二分还能这样用。

#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
vector<pii>a,b;
int pre1[100000+10],pre2[100000+10];
int main()
{
    a.clear();
    b.clear();
    int n,c,d,flag=false,ans=0,tmp=0;
    cin>>n>>c>>d;
    //cout<<n<<" "<<c<<" "<<d<<endl;
    for(int i=1;i<=n;i++)
    {
        int bea,cos;
        char ch;
        cin>>bea>>cos;
        scanf(" %c",&ch);
        //cout<<bea<<" "<<cos<<" "<<ch<<endl;
        if(ch=='C')
            a.push_back(make_pair(cos,bea));
        else
            b.push_back(make_pair(cos,bea));
    }
    sort(a.begin(),a.end());
    sort(b.begin(),b.end());
    for(int i=0;i<a.size();i++)//第一种情况从c和d类型的物品里分别选一个能选到的最大val的东西
    {
        if(i==0)
            pre1[i]=a[i].second;
        else
            pre1[i]=max(pre1[i-1],a[i].second);
        if(a[i].first<=c)
            ans=max(ans,a[i].second);
    }
    for(int i=0;i<b.size();i++)
    {
        if(i==0)
            pre2[i]=b[i].second;
        else
            pre2[i]=max(pre2[i-1],b[i].second);
        if(b[i].first<=d)
            tmp=max(tmp,b[i].second);
    }
    /*
    for(int i=0;i<a.size();i++)
        cout<<a[i].first<<"  "<<a[i].second<<"      ";
    cout<<endl;
    for(int i=0;i<a.size();i++)
        cout<<pre1[i]<<"      ";
    cout<<endl;
    cout<<"****************************************"<<endl;
    for(int i=0;i<b.size();i++)
        cout<<b[i].first<<"  "<<b[i].second<<"      ";
    cout<<endl;
    for(int i=0;i<b.size();i++)
        cout<<pre2[i]<<"      ";
    cout<<endl;
    */
    if(ans&&tmp)
    {
        flag=true;
        ans+=tmp;
    }
    else
        ans=0;
    for(int i=1;i<a.size();i++)//第2种情况,从c类型的物品里选2件,过程是直接选一件,然后再二分找另外一件能取到最大价值的物品
    {
        if(a[i].first>=c)
            continue;
        int rest=c-a[i].first,low,up,mid,pos=-1;
        low=0;
        up=i-1;
        while(low<=up)
        {
            mid=(low+up)>>1;
            if(a[mid].first<=rest)
            {
                pos=mid;
                low=mid+1;
            }
            else
                up=mid-1;
        }
        if(pos!=-1)
        {
            ans=max(ans,a[i].second+pre1[pos]);
            flag=true;
        }
    }
    for(int i=1;i<b.size();i++)//第3种情况,从d类型的物品里选2件,过程是直接选一件,然后再二分找另外一件能取到最大价值的物品
    {
        if(b[i].first>=d)
            continue;
        int rest=d-b[i].first,low,up,mid,pos=-1;
        low=0,up=i-1;
        while(low<=up)
        {
            mid=(low+up)>>1;
            if(b[mid].first<=rest)
            {
                pos=mid;
                low=mid+1;
            }
            else
                up=mid-1;
        }
        if(pos!=-1)
        {
            ans=max(ans,b[i].second+pre2[pos]);
            flag=true;
        }
    }
    if(flag)
        cout<<ans<<endl;
    else
        cout<<0<<endl;
    return 0;
}

 

posted @ 2018-08-21 23:27  eason99  阅读(72)  评论(0编辑  收藏  举报