洛谷 P14635 [NOIP2025] 糖果店 题解

洛谷 P14635 [NOIP2025] 糖果店 题解

题目链接

洛谷 P14635 [NOIP2025] 糖果店

思路分析

Trick 1:每买 \(2\) 个糖果 \(i\) 的价格固定为 \(x_i+y_i\),再买单个的该糖果价格为 \(x_i\)。

证明:糖果价格的循环周期为 \(2\)。

Trick 2:最多只有一种糖果 \(X\) 会被买 \(2\) 次及以上。

证明:如果有另一种糖果也被买 \(2\) 次以上,记该糖果为 \(A\) 糖果,买 \(a\) 个,另一种糖果为 \(B\) 糖果,买 \(b\) 个。

  • 若 \(A\) 糖果购买 \(2\) 次的价格小于等于 \(B\) 糖果,则将买 \(b\) 个 \(B\) 糖果换为买 \(2\Big\lfloor\dfrac{b}{2}\Big\rfloor\) 个 \(A\) 糖果和 \(b\bmod2\) 个 \(B\) 糖果必定不劣
  • 若 \(A\) 糖果购买 \(2\) 次的价格大于 \(B\) 糖果,则将买 \(a\) 个 \(A\) 糖果换为买 \(2\Big\lfloor\dfrac{a}{2}\Big\rfloor\) 个 \(B\) 糖果和 \(a\bmod2\) 个 \(A\) 糖果必定更优

综上,无论如何调整必定只有一个糖果被买 \(2\) 次及以上。

更进一步,由上述的调整方法可得这个糖果必定是买 \(2\) 次代价最小的糖果。

Trick 3:只买 \(1\) 次的那些糖果必定是剩下糖果中 \(x_i\) 最小的那些糖果。

证明:贪心即可。

综上,我们可以枚举有多少件物品只买了 \(1\) 次,利用前缀和算出这些糖果的代价和,然后计算还能买多少个糖果 \(X\) 即可。具体地,假设有 \(i\) 个物品只买了 \(1\) 次,总代价为 \(s\),那么还能消耗不超过 \(m-s\) 的代价,若糖果 \(X\) 买 \(2\) 次的代价和为 \(p\),则可以买 \(\Big\lfloor\dfrac{m-s}{p}\Big\rfloor\) 组,再乘以 \(2\) 并加上一开始的 \(i\) 个物品即为买到的糖果数,取 \(\max\) 输出即可。由计算过程可得不能买负数个糖果 \(X\),故 \(m-s\ge0\),即应满足 \(s\le m\)。时间复杂度 \(\mathcal O(n\log n)\),瓶颈在排序。

代码呈现

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=1e5+10;
int n,p=INT_MAX;
ll m,s,ans=0;
int a[N],b[N];

int main(){
    scanf("%d%lld",&n,&m);
    for (int i=1;i<=n;++i)
        scanf("%d%d",a+i,b+i),p=min(p,a[i]+b[i]);
    sort(a+1,a+n+1);
    for (int i=0;i<=n;++i){
        s+=a[i];
        if (s>m) break;
        ans=max(ans,i+(m-s)/p*2);
    }
    printf("%lld",ans);
    return 0;
}
posted @ 2026-10-01 22:30  CodingJuRuo  阅读(6)  评论(0)    收藏  举报