【题解】 P6364 1024 程序员节发橙子
蒟蒻题解第2篇
先分析下题意:
- 输入一个数列。
- 根据数列中元素的值按要求分配物品。
- 求分配物品数量总和的最小值。
要求:
设 \(|x|\) 表示数列中第 \(x\) 个元素的值,\(-x-\) 表示第 \(x\) 个元素应分配的物品数量。
-
若 \(|x+1|>|x|\),则分配方案需满足 \(-x+1->-x-\)。
-
若 \(|x+1|=|x|\),则分配方案需满足 \(-x+1-=-x-\)。
-
若 \(|x-1|>|x|\),则分配方案需满足 \(-x-1->-x-\)。
-
若 \(|x-1|=|x|\),则分配方案需满足 \(-x-1-=-x-\)。
再思考波算法:
仔细思考下题意分析,你会发现这道题可以简化为在数列里跑两遍不降子序列(序列里分配物品数量+1),正着跑一遍,反着跑一遍,就可以满足临近两个同学的要求了。
最后实现代码:
154ms,8.25MB
#include<bits/stdc++.h>
#define maxn 1000010
#define ull unsigned long long
using namespace std;
int a[maxn],orange[maxn],n;
ull answer;//不开unsigned long long 会部分WA
int main()
{
memset(a,0,sizeof(a));
memset(orange,0,sizeof(orange));
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=2;i<=n;i++)//正着跑不降子序列
{
if(a[i-1]<a[i])
orange[i]=orange[i-1]+1;
if(a[i-1]==a[i])
orange[i]=orange[i-1];
}
for(int i=n;i>=2;i--)//倒着跑不降子序列
{
if(a[i]<a[i-1])
orange[i-1]=max(orange[i-1],orange[i]+1);
if(a[i-1]==a[i])
orange[i-1]=orange[i];
}
answer=n;//因为每个人至少要分1个橙子 所以答案初值为n
for(int i=1;i<=n;i++)
answer+=orange[i];
printf("%lld",answer);
return 0;
}