P8298 [COCI2012-2013#2] POPUST题解
贪心好题
P8298 [COCI2012-2013#2] POPUST
前记
蒟蒻第一篇题解
题目描述
Mirko 像熊一样饥饿,发现了一家当地餐馆。这家餐厅提供
Mirko 无法决定点多少菜。为了更简单地作出决定,他向你求助。对于任意
贪心思想
观察此样例
3
10 5
9 3
10 5这道题的突破点在于:由题意得,我们并不关注点菜顺序,所以对于每个
所以我们先按照
9 3
10 5
10 5排序后我们可以看出,由于
但是我们发现,面对下面这个样例,这样就是错误的。
3
1 3
114514 7
1919810 9按照上面的式子计算,当
这时我们要取出前
设取出
贪心使
得
综上所述,两种方案取较小值。
总结就是两种情况:
1.完完全全选择最小的
2.选择一个较大的
代码实现
根据上面的式子,我们发现我们只需要维护三个东西
然后边更新边输出就好了,其实代码非常简单,而且也没什么可说的
#include<cstdio>
#include<algorithm>
#define int long long\\要long long
using namespace std;
const int MAXN=5e5+10;
struct d{int a,b;}p[MAXN];\\a[i]和b[i]
int n,pre[MAXN],MIN[MAXN],c[MAXN];\\三个数组分别对应上面的三个
inline bool cmp(d x,d y){return x.b<y.b;}\\以b[i]为关键字排序
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld%lld",&p[i].a,&p[i].b);
sort(p+1,p+1+n,cmp);MIN[n+1]=0x3f3f3f,c[0]=0x3f3f3f;\\赋初值
for(int i=1;i<=n;i++)\\正着预处理
{
pre[i]=pre[i-1]+p[i].b;
c[i]=min(c[i-1],p[i].a-p[i].b);
}
for(int i=n;i>=1;i--) MIN[i]=min(MIN[i+1],p[i].a);\\反向预处理
for(int i=1;i<=n;i++) printf("%lld\n",min(pre[i-1]+MIN[i],pre[i]+c[i-1]));\\输出
return 0;
}