本文主要是介绍P4801 [CCO 2015]饥饿的狐狸,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
R e s u l t Result Result
H y p e r l i n k Hyperlink Hyperlink
https://www.luogu.com.cn/problem/P4801
D e s c r i p t i o n Description Description
有 n n n个东西,第 i i i个物品的温度是 a i a_i ai,有一杯温度为 w w w的水(你可以认为它的水量无穷)
吃掉每个物品的代价是这次吃的物品的温度与上次吃的物品的温度差值,在每次吃东西的时候,你也可以选择先喝一杯水,这样就默认你上次吃的物品是水
假设你已经喝了一杯水,试着安排一种吃东西的顺序,使得代价最小/最大
数据范围: n ≤ 1 0 5 , w ≤ 1 0 9 n\leq 10^5,w\leq 10^9 n≤105,w≤109
S o l u t i o n Solution Solution
贪心,排序是显而易见的
考虑最大价值,显然我们是每次选择最大的和最小的判断即可,中间判断是否喝水更优就好了,注意初始化要喝一杯水
最小价值显然是升序或者倒序吃东西,如果没有喝水的限制,答案显然是 a n − a 1 a_n-a_1 an−a1
考虑水的温度对答案的贡献
假设 w ∈ [ a 1 , a n ] w\in[a_1,a_n] w∈[a1,an],显然我们可以在最后一个与 a 1 a_1 a1相等的食物后面喝一杯水,就能抵消刚开始喝的那杯水产生的代价,即答案为 a n − a 1 a_n-a_1 an−a1
假设 w < a 1 w<a_1 w<a1,由于题目要求那杯水必须喝,所以答案要加上 a 1 − w a_1-w a1−w,答案变成 a n − w a_n-w an−w
假设 w > a n w>a_n w>an,跟上面的一个道理,此时我们反过来吃,答案要加上 w − a n w-a_n w−an,答案变成 w − a 1 w-a_1 w−a1
最终化成的式子就是 max { 0 , a n − w } + max { 0 , w − a 1 } \max\{0,a_n-w\}+\max\{0,w-a_1\} max{0,an−w}+max{0,w−a1}
时间复杂度: O ( n log n ) O(n\log n) O(nlogn)
C o d e Code Code
#include<cstdio>
#include<cctype>
#include<algorithm>
#define LL long long
using namespace std;
int n,lst;
LL maxn,w,a[100010],now,l,r;
inline LL read()
{char c;LL d=1,f=0;while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;return d*f;
}
signed main()
{n=read();w=read();for(register int i=1;i<=n;i++) a[i]=read();sort(a+1,a+1+n);printf("%lld ",max(0ll,a[n]-w)+max(0ll,w-a[1]));lst=w;l=1;r=n;now=0;for(register int i=1;i<=n;i++) if(i&1) now+=max(abs(a[l]-lst),abs(a[l]-w)),lst=a[l++];else now+=max(abs(a[r]-lst),abs(a[r]-w)),lst=a[r--];maxn=now;lst=w;l=1;r=n;now=0;for(register int i=1;i<=n;i++) if(i&1) now+=max(abs(a[r]-lst),abs(a[r]-w)),lst=a[r--];else now+=max(abs(a[l]-lst),abs(a[l]-w)),lst=a[l++];printf("%lld",max(maxn,now));
}
这篇关于P4801 [CCO 2015]饥饿的狐狸的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!