CodeForces - 799C Fountains(二分)

题目链接:http://codeforces.com/contest/799/problem/C

题意:给c,d两个类型的喷泉,你有c的货币c个,d的货币d个,每个类型的货币只能买对应类型的喷泉,每个喷泉有一个美丽值和价格,问你必须买两个喷泉的最大美丽值是多少。

思路:先按价格升序排序,再用两个数组分别去存前缀美丽值的最大值,然后枚举每个位置二分剩下钱能获得的最大价值。当位置为i时,二分范围为0~i-1,这样是为了避免重复(简单来说就是枚举两个喷泉中价格的更大值),遇到可选值(价格小于等于剩下钱)就用pos记录位置,最后就是第i个的价格加上0~pos的最大美丽值(前缀记录)。

代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define fuck(x) cout<<"<"<<x<<">"<<endl
#define fi first
#define se second
#define pb push_back 
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<LL, LL> pii;
const double PI = acos(-1.0);
const LL INFLL = 0x3f3f3f3f3f3f3f3fll;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;


int n,c,d;
struct node{
	int b,p;
}C[maxn],D[maxn];
bool cmp(node x,node y){
	if (x.p!=y.p) return x.p<y.p;
	return x.b<y.b;
}
int f[maxn],h[maxn];
int main() {
	cin>>n>>c>>d;
	int cnt1=0,cnt2=0;
	for (int i=0;i<n;i++){
		int x,y;
		char z;
		cin>>x>>y>>z;
		if (z=='C') C[cnt1].b=x,C[cnt1++].p=y;
		else D[cnt2].b=x,D[cnt2++].p=y;
	}
	sort(C,C+cnt1,cmp);
	sort(D,D+cnt2,cmp);
	for (int i=0;i<cnt1;i++){
		if (i==0) f[i]=C[i].b;
		else f[i]=max(f[i-1],C[i].b);
	}
	for (int i=0;i<cnt2;i++){
		if (i==0) h[i]=D[i].b;
		else h[i]=max(h[i-1],D[i].b);
	}
	int ans1=0,ans2=0,ans3=0;
	for (int i=1;i<cnt1;i++){
		if (C[i].p>=c) break;
		int l=0,r=i-1;
		int tmp=c-C[i].p;
		int pos=-1;
		while (l<=r){
			int m=(l+r)/2;
			if (C[m].p<=tmp){
				pos=m;
				l=m+1;
			}
			else r=m-1;
		}
		if (pos!=-1&&f[pos]) ans1=max(ans1,C[i].b+f[pos]);
	}
	for (int i=1;i<cnt2;i++){
		if (D[i].p>=d) break;
		int l=0,r=i-1;
		int tmp=d-D[i].p,pos=-1;
		while (l<=r){
			int m=(l+r)/2;
			if (tmp>=D[m].p){
				pos=m;
				l=m+1;
			}
			else r=m-1;
		}
		if (pos!=-1&&h[pos]) ans3=max(ans3,D[i].b+h[pos]);
	}
	int tmp1=-1,tmp2=-1;
	for (int i=0;i<cnt1;i++){
		if (C[i].p<=c) tmp1=max(tmp1,C[i].b);
	}
	for (int i=0;i<cnt2;i++) {
		if (D[i].p<=d) tmp2=max(tmp2,D[i].b);
	}
	if (tmp1==-1||tmp2==-1) ans2=0;
	else ans2=tmp1+tmp2;
	cout<<max(ans1,max(ans2,ans3))<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值