D. Riverside Curio
D. Riverside Curio
? https://codeforces.com/problemset/problem/957/D
Arkady decides to observe a river for n consecutive days. The river’s water level on each day is equal to some real value.
Arkady goes to the riverside each day and makes a mark on the side of the channel at the height of the water level, but if it coincides with a mark made before, no new mark is created. The water does not wash the marks away. Arkady writes down the number of marks strictly above the water level each day, on the i-th day this value is equal to mi.**
Define di as the number of marks strictly under the water level on the i-th day. You are to find out the minimum possible sum of di over all days. There are no marks on the channel before the first day.
Input
The first line contains a single positive integer n (1?≤?n?≤?105) — the number of days.
The second line contains n space-separated integers m1,?m2,?…,?mn (0?≤?mi?<?i) — the number of marks strictly above the water on each day.
Output
Output one single integer — the minimum possible sum of the number of marks strictly below the water level among all days.
Examples
input
6 0 1 0 3 0 2output
6input
5 0 1 2 1 2output
1input
5 0 1 1 2 2output
0Note
In the first example, the following figure shows an optimal case.
Note that on day 3, a new mark should be created because if not, there cannot be 3 marks above water on day 4. The total number of marks underwater is 0?+?0?+?2?+?0?+?3?+?1?=?6.
In the second example, the following figure shows an optimal case.
題意:
一個人每天去河邊看水位,水的高度與之前不同就在這個高度做標記,如果這個高度已經標記過了就不做任何事,數組m有n個元素,m 1代表第一天來的時候,看到的水面上的標記,一定是0(因為第一天才開始標記),m 2代表第二天看到的水面上的標記(因為水位會變),以此類推。求所有天中嚴格低于水位的標記數目的最小和
分析:
難點主要是推式子,我們只要知道每天總共有多少個標記,和每天在水面上的標記數,相減再-1(減去剛好貼著水面的標記)就是在水面下的標記了,最后求和就是答案了。
設t[i]為第i天的劃線數量,第一天為1,m[i]為第i天嚴格在上面的數,b[i]為第i天嚴格在下面的數,那么有
b[i]=t[i]?m[i]?1b[i] = t[i]-m[i]-1 b[i]=t[i]?m[i]?1
現在問題就是求b數組,也就是求在水面下的標記數(這里絕對是個難點)。
由一個例子,Day 1時m 1是0,此時標記數就是0+1=1(因為當天標記的是貼著水面的,所以要加一),Day 2時m 2是1,此時標記數就是1+1=2,但是到了Day 3,m 3就變成了0,因為這是水位突然猛漲,人家已經看不到之前的標記了,既然變成0了,那不就不知道第三天究竟有幾個標記了嗎?
確實不知道,但我們知道的是,此時的標記數不是2個就是3個。為什么?因為此時看不到標記,水位要么回到了之前的高度(標記貼著水面),要么高于之前的標記。我們要確定是2還是3,就得看后面。因為Day 4時看到了3個標記,所以Day 3的時候只能是3個標記,也就是說,水位上升的時候要看后面才能確定標記數。
先正向遍歷一遍,水位下降時(m增大),我們可以確定有幾個標記(m+1),水位上升到要標記新的標記時,就取昨天的標記數。合并到一起就是:
for(int i=1;i<=n;++i) t[i]=max(t[i-1],m[i]+1);為了求水位上升時的標記數,需要再反向遍歷一遍。
for(int i=n-1;i>=1;--i)if(t[i+1]-t[i]>1)t[i]=t[i+1]-1;注意,這里判斷相鄰兩天標記數之差不能超過1,為什么?因為你每次來河邊標記,要么不標記,要么就標記一次呀,所以兩邊最多只能相差1,且左邊等于右邊減1。為什么不是右邊等于左邊加1?前面已經說了,比如第三天的標記數不是2個就是3個,我們取了第二天的標記數(2),所以要讓標記數盡量大,讓左邊大一點,而不是讓右邊小一點。
代碼:
#include<iostream> #include<algorithm> #define int long long #define Please return #define AC 0 using namespace std; const int N=1e6+1; void fastio(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);} int a[N]; int t[N]; signed main() {fastio();int n,ans=0;cin>>n;for(int i=1;i<=n;++i)cin>>a[i];for(int i=1;i<=n;++i) t[i]=max(t[i-1],a[i]+1);for(int i=n-1;i>=1;--i)if(t[i+1]-t[i]>1)t[i]=t[i+1]-1;for(int i=1;i<=n;++i)ans+=t[i]-a[i]-1;cout<<ans<<endl;Please AC; }總結
以上是生活随笔為你收集整理的D. Riverside Curio的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WikiTaxi_Importer_1.
- 下一篇: 激光检测----激光原理简述