P14635 [NOIP2025] 糖果店 / candy 题解
前言
考场的想法,结果2.5h都还有一些细节没处理好导致有点小爆炸。
思路
首先阅读题目和样例,根据样例1可以发现:对于大量购买同一种糖果的情况,平均每颗的价格为
再看到样例2,发现我们不能只买
可以发现对于
有人可能会问:假如说单买的糖果里有可以买第二颗的情况怎么办?但这其实不会成立,如果单买的糖果
时间复杂度
主要集中在 sort 的排序上,为
代码
一些解释和注意事项都写在注释里了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,mn=1e18,p;
struct node
{
ll x,y;
}cd[100005];
bool cmp(node a,node b)
{
if(a.x==b.x) return a.y<b.y;
else return a.x<b.x;
}
ll check(ll sum,ll nk)//算买p的颗数并加到当前情况的答案中,注意这里的数据类型是long long
{
ll w=m-sum;//剩余的钱数,注意这里的数据类型也是long long
nk+=(w/mn)*2;
if(w-(w/mn)*mn>=cd[p].x) nk++;//求买p的颗数,注意这里等于的时候也是可以买一颗p的
return nk;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> m;
for(int i=1;i<=n;i++)
{
cin >> cd[i].x >> cd[i].y;
mn=min(mn,cd[i].x+cd[i].y);//mn是x+y最小值
}
sort(cd+1,cd+n+1,cmp);
for(int i=1;i<=n;i++) if(cd[i].x+cd[i].y==mn) p=i;//p是x+y最小的位置
ll sum=0,ans=check(0,0),mk=0;//mk是当前买的散的糖果数,注意ans一开始要为只买p糖果时的答案
for(int i=1;i<=n;i++)
{
if(i==p) continue;//糖果p在后面check函数中会单独统计,因此在这里不考虑
sum+=cd[i].x;
if(sum>m) break;//超过m就说明这颗和之后的糖果都买不下了
mk++;
ans=max(ans,check(sum,mk));
}
cout << ans;
return 0;
}