大树的水塘
单点时限: 2.0 sec
内存限制: 512 MB
那一天,世界上所有的人类都……变成了石头!
3700年后,千空和大树从石头中苏醒过来,但是世界发生了翻天覆地的变化,人类文明已经不复存在
天才少年千空立志用自己的科学知识在这个「石之世界」中重建文明
为了生存,淡水是必不可少的,每次都用海水进行蒸馏会比较麻烦,所以千空决定让大树建造一个水塘来存储雨水
水塘建造在一个无限长,高度不超过100,宽度为1的峡谷里,所以只需要往里面填石头,即可达到蓄水的目的
当大树建造好水塘让千空去检查的时候,千空一口老血喷了出来:因为大树是一个体力笨蛋,所以建造的水塘底部是参差不齐的,这使得建造蓄水相同体积的水塘,大树多用了好多石头
已知每块石头中的规格是1×1×1,水塘的长度为N,宽度为1,在第i位置,大树放了ai个石头
设大树建造的水塘蓄水量为V
请你求出在长度和宽度不变的情况下,建造一个蓄水量不小于V的水塘最多可以节约多少石头
输入格式
单组输入
第一行一个数N (1≤N≤107)表示水塘的长度
第二行有N个非负数xi (0≤xi≤100),表示第i个位置上放的石头数
输出格式
输出有两行
第一行输出大树建造的水塘的蓄水量V
第二行输出最多可以节约多少石头
样例
input
5
2 1 3 1 3
output
3
8
提示
大树的水塘长这样:
最节约石头的水塘长这样:
这个题就是用两个数组分别进行保存从左边和右边到该点的最高的石头是多少,然后从第二个到第n-1个点进行遍历,求出每一个可以存的水的数量,然后累加求和即可求出积水的数量,最节约的方法就是仅在两边加石头中间存水即可,然后一开始进行所有的石头累加,减去存上面求出的积水需要的最少的石头,就是可以节约的石头。
Code:
#include<bits/stdc++.h>
using namespace std;
const int N=11111111;
int a[N];
int b[N];
int c[N];
int main()
{
int n;
cin>>n;
int s=0;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
s+=a[i];
}
b[0]=a[0];
for(int i=1;i<n;i++)
b[i]=max(b[i-1],a[i]);
c[n-1]=a[n-1];
for(int i=n-2;i>=0;i--)
c[i]=max(c[i+1],a[i]);
int sum=0;
int p,pp,q;
for(int i=1;i<n-1;i++){
p=b[i-1]-a[i];
pp=c[i+1]-a[i];
if(p>0&&pp>0){
q=min(p,pp);
sum+=q;
}
}
printf("%d\n",sum);
if(n<=2)printf("%d\n",s);
else{
int w=sum/(n-2);
if(w*(n-2)<sum)w++;
printf("%d",s-2*w);
}
return 0;
}