5961. 【NOIP2018提高組D1T1】鋪設道路
阿新 • • 發佈:2018-12-22
Time Limits: 1000 ms Memory Limits: 524288 KB
Description
春春是一名道路工程師,負責鋪設一條長度為 n 的道路。
鋪設道路的主要工作是填平下陷的地表。整段道路可以看作是 n 塊首尾相連的區域,一開始,第 i 塊區域下陷的深度為 d[i] 。
春春每天可以選擇一段連續區間 [L,R] ,填充這段區間中的每塊區域,讓其下陷深度減少1。在選擇區間時,需要保證,區間內的每塊區域在填充前下陷深度均不為 0 。
春春希望你能幫他設計一種方案,可以在最短的時間內將整段道路的下陷深度都變為 0 。
Input
輸入檔名為road.in。
輸入檔案包含兩行,第一行包含一個整數 n ,表示道路的長度。
第二行包含 n 個整數,相鄰兩數間用一個空格隔開,第 i 個整數為 d[i] 。
Output
輸出檔名為road.out。
輸出檔案僅包含一個整數,即最少需要多少天才能完成任務。
Sample Input
【輸入輸出樣例1】
6
4 3 2 5 3 5
【輸入輸出樣例2】
見選手目錄下的road/road2.in和road/road2.ans。
Sample Output
9
Data Constraint
【樣例解釋】
一種可行的最佳方案是,依次選擇:
[1,6],[1,6],[1,2],[1,1],[4,6],[4,4],[4,4],[6,6],[6,6]
Hint
對於 30% 的資料,1≤n≤10;
對於 70% 的資料,1≤n≤1000;
對於 100% 的資料,1≤n≤100000,0≤di≤10000。
Solution
100%: 每次選擇 中最小的數作為覆蓋的高度,然後區間被分成 和 ,用線段樹維護
100%: 若令,則
Code
#include<algorithm>
#include<cstdio>
#include<cctype>
#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);
}