春春是一名道路工程师,负责铺设一条长度为 n 的道路。
铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n 块首尾相连的区域,一开始,第 i 块区域下陷的深度为 d[i] 。
春春每天可以选择一段连续区间 [L,R] ,填充这段区间中的每块区域,让其下陷深度减少1。在选择区间时,需要保证,区间内的每块区域在填充前下陷深度均不为 0 。
春春希望你能帮他设计一种方案,可以在最短的时间内将整段道路的下陷深度都变为 0 。
输入文件名为road.in。
输入文件包含两行,第一行包含一个整数 n ,表示道路的长度。
第二行包含 n 个整数,相邻两数间用一个空格隔开,第 i 个整数为 d[i] 。
输出文件名为road.out。
输出文件仅包含一个整数,即最少需要多少天才能完成任务。
【输入输出样例1】
6
4 3 2 5 3 5
【输入输出样例2】
见选手目录下的road/road2.in和road/road2.ans。
9
【样例解释】
一种可行的最佳方案是,依次选择:
[1,6],[1,6],[1,2],[1,1],[4,6],[4,4],[4,4],[6,6],[6,6]
对于 30% 的数据,1≤n≤10;
对于 70% 的数据,1≤n≤1000;
对于 100% 的数据,1≤n≤100000,0≤di≤10000。
100%: O ( n l o g n ) O(nlogn) O(nlogn) 每次选择 [ l , r ] [l,r] [l,r] 中最小的数作为覆盖的高度,然后区间被分成 [ l , r ′ ] [l,r'] [l,r′] 和 [ l ′ , r ] [l',r] [l′,r],用线段树维护
100%: O ( n ) O(n) O(n) 若令 a 0 = a n + 1 = 0 a_0=a_{n+1}=0 a0=an+1=0,则 a n s = ∑ i = 1 n m a x ( 0 , a i − a i − 1 ) ans=\sum_{i=1}^{n}max(0,a_i-a_{i-1}) ans=∑i=1nmax(0,ai−ai−1)
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int N=1e5+5;
int n,a[N],z[N];
inline void read(int &n)
{
int x=0,w=0; char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
n=w?-x:x;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int main()
{
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
read(n);
int cnt=0,ans=0;
fo(i,1,n) read(a[i]);
fo(i,1,n)
{
int now=cnt;
while(cnt&&a[i]<=z[cnt]) --cnt;
if(now==cnt) ans+=(a[i]-z[cnt]);
z[++cnt]=a[i];
}
write(ans);
}