924C Riverside Curio

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 i -th day this value is equal to mi m i .

Define di d i as the number of marks strictly under the water level on the i i -th day. You are to find out the minimum possible sum of di d i over all days. There are no marks on the channel before the first day.

Input

The first line contains a single positive integer n(1n105) n ( 1   ≤   n   ≤   105 ) — the number of days.

The second line contains n space-separated integers m1,m2 m 1 ,   m 2 , …,  mn m n (0mi<i) ( 0   ≤   m i   <   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

inputCopy

6
0 1 0 3 0 2

output

6

inputCopy

5
0 1 2 1 2

output

1

inputCopy

5
0 1 1 2 2

output

0

Note

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.

大概意思就是说,每天画一条水平线(若与之前的重合则相当于线的数量不变,每天告诉你画的这条线上的线有多少条)。要每天这条线下的线的数量之和最小,求这个最小值。
传送门!!!






解:

感觉此题很妙妙啊,首先分析得出要是线下数量最少,因为线上是定值,所以转而求每天线的总数最少。
设第 i i 天,线上数为mi,线下数为 di d i ,线总数为 ti t i 。很明显 ti=mi+1+di t i = m i + 1 + d i
其次我们列出几个限制条件:
1.titi1 1. t i ≥ t i − 1
2.timi+1 2. t i ≥ m i + 1
3.titi1+1 3. t i ≤ t i − 1 + 1 (因为每天只能画一条线)
对于前两个条件,我们从左向右递推,可以求出每天满足条件的最小值。(此时不满足第三个条件。)如何处理第三个条件?我们会想到从右向左递推,如果 ti+1<ti+1 t i + 1 < t i + 1 ,那么把 ti t i 赋值为 ti+1 t i + 1 ,继续递推。
然后,居然就完了!!!
贴上代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int m[100005],d[100005],t[100005];
int n;
long long ans;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      scanf("%d",&m[i]);
    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]<t[i+1]-1)
        t[i]=t[i+1]-1;
    for(int i=1;i<=n;i++)
      ans+=t[i]-1-m[i];
    cout<<ans;
} 

惊了,这道题代表了一类乱搞的题。记得以前看过一道洞穴灌水的题,也是从左从右各扫一次取min才能得到答案。有没有一种启发?不一定一次遍历就可以求出答案,可能答案需要多次遍历并组合遍历结果。这一题很有意思,就是需要两遍限制才能得到答案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值