题意:n件物品,有金币C和砖石D n,c,d<=1e5,每件物品有价值和花费(类型为c或者d),挑选正好两件物品使得价值最大
两件物品为CC,按花费排序,防止重复,则枚举两件中花费高的那一件p[x],
于是剩下一件的选择范围限定在前[i-1]件内,剩下的钱c-p[x]递减,用一个游标pos(或者二分)记录最后一个小于c-p[x],并维护前缀min[i-1,pos]内最大能取到的价值即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
const int N=2e5+20;
int n,c,d;
char op;
vector<ii> a,b;
int f[N],h[N];
int main()
{
while(cin>>n>>c>>d)
{
int v,p;
a.clear(),b.clear();
for(int i=0;i<n;i++)
{
scanf("%d%d",&v,&p);
cin>>op;
if(op=='C')
a.push_back(ii(p,v));
else
b.push_back(ii(p,v));
f[i]=h[i]=0;
}
sort(a.begin(),a.end());
sort(b.begin(),b.end());
bool flag=false;
int ans=0,res=0;
for(int i=0;i<a.size();i++)
{
if(i==0)
f[i]=a[i].second;
else
f[i]=max(f[i-1],a[i].second);
if(c>=a[i].first)
ans=max(ans,a[i].second);
}
for(int i=0;i<b.size();i++)
{
if(i==0)
h[i]=b[i].second;
else
h[i]=max(h[i-1],b[i].second);
if(d>=b[i].first)
res=max(res,b[i].second);
}
if(ans&&res)
ans+=res,flag=true;//CD
for(int i=1;i<a.size();i++)//CC
{
if(a[i].first>=c)
break;
int x=c-a[i].first,pos=-1;
int l=0,r=i-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(a[mid].first<=x)
{
pos=mid;
l=mid+1;
}
else
r=mid-1;
}
if(pos!=-1&&f[pos])
ans=max(ans,a[i].second+f[pos]),flag=true;
}
for(int i=1;i<b.size();i++)//DD
{
if(b[i].first>=d)
break;
int x=d-b[i].first,pos=-1;
int l=0,r=i-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(b[mid].first<=x)
{
pos=mid;
l=mid+1;
}
else
r=mid-1;
}
if(pos!=-1&&h[pos])
ans=max(ans,b[i].second+h[pos]),flag=true;
}
if(flag==false)
ans=0;
cout<<ans<<endl;
}
return 0;
}