社区讨论

90分求助

P4040[AHOI2014/JSOI2014] 宅男计划参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lp13k6al
此快照首次捕获于
2023/11/16 19:17
2 年前
此快照最后确认于
2023/11/16 20:50
2 年前
查看原帖
为了防止超出long long范围,我把判断改成了```cpp v[i].second+1>1e18/x
CPP

但还是没过


```cpp
#include<iostream>
#include<vector>
#include<algorithm>
#define ll uint64_t
using namespace std;
ll m,f;
int n;
vector< pair<ll,ll> > v;
bool cmp(pair<ll,ll> s1,pair<ll,ll> s2){
	if(s1.first==s2.first) return s1.second>s2.second;
	return s1<s2;
}
void input(){  //读入数据
	cin>>m>>f>>n;
	for(int i=0;i<n;i++) {
		pair<ll,ll> tem;
		cin>>tem.first>>tem.second;
		v.push_back(tem);
	}
}
void sort_v(){  //将食物按价格排序,删去价格高但保质期低的食物,修改 n=v.size() 
	sort(v.begin(),v.end(),cmp);
	auto pre = v.begin();
	for(auto it = v.begin()+1;it!=v.end();it++){
		if((*it).second<=(*pre).second) {
			v.erase(it);
			it = pre;
		}
		pre = it;
	}
	n = v.size();
}
ll get_ans(ll x){  //表示买x次外卖能活几天 
	if(x==0) return 0;
	ll w = m-x*f;
	ll ans = 0;
	for(int i=0;i<n;i++){ //表示买到了第几种食物 
		ll num = w/v[i].first; //这种食物最多能买多少个 
		if(num==0) break;  //一个都买不了,不买了 
		ll max_num;  //表示这种食物最多能买几个不过期的 
		if(i==0){
			if(v[i].second+1>1e18/x) {
				max_num = num+1;
			}
			else max_num = (v[i].second+1)*x;
		}
		else{
			if(v[i].second-v[i-1].second>1e18/x) {
				max_num = num+1;
			}
			else max_num = (v[i].second-v[i-1].second)*x;
		}
		if(num>max_num) num = max_num;//如果买的食物超过了保质期,就只买保质期内的食物 
		ans += num;
		w -= num*v[i].first;
	}
	return ans;
}
int main(){
	input();
	sort_v();
	//此题是单峰函数,使用三分来求解最大值 
	ll r = m/(f+v[0].first);
	ll l = 0;
	ll mid,midl,midr;
	while(r-l>1){  //以外卖次数进行三分 
		mid = (l+r)/2;
		midl = mid-1;
		midr = mid+1;
		if(get_ans(midl)>get_ans(midr)) r = mid;
		else l = mid;
	}
	cout<<max(get_ans(l),get_ans(r));
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...