Codeforces 957D - Riverside Curio 【思维】

本文介绍了一种关于河流观测的算法问题,通过记录每日河流水位变化及已标记的线上方标记数量,来求解最小化的线下标记总数。采用逆向思维与累积更新策略,实现最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


D. Riverside Curio

time limit per test   1second

memory limit per test      256megabytes

Arkady decides to observe a river for n consecutivedays. The river's water level on each day is equal to some real value.

Arkady goes to the riverside each dayand 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 waterdoes not wash the marks away. Arkady writes down the number of marks strictlyabove the water level each day, on the i-th day this value is equal to mi.

Define di as the number of marks strictly underthe 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 singlepositive integer n (1 ≤ n ≤ 105) — thenumber of days.

The second line contains n space-separatedintegers 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

Copy

6
0 1 0 3 0 2

Output

6

Input

5
0 1 2 1 2

Output

1

Input

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 totalnumber of marks underwater is 0 + 0 + 2 + 0 + 3 + 1 = 6.

In the second example, the following figure shows an optimal case.

 





【题意】

有一个人每天会去观察一条河流的水位,每次在当前水位上画一条线(如果重复则不画)

现在告诉你他每天去看时,当前水位的上方(严格大于)画了几条线。

问每天去看时,当前水位的下方(严格小于)画线条数d[i]总和的最小值。


【思路】

我们用sum[i]表示,前i天一共画了多少条线,由于sum[i]=d[i]+a[i]+1,那么最小化sigma(d[i])就转化为了最小化sigma(sum[i)。

于是我们尽量使得每个sum[i]小,由于sum[i]必须满足:

  1. sum[i]>=max(sum[i-1],a[i]+1)
  2. sum[i]>=sum[i+1]-1 每天最多画一条线

条件1很好满足,为了满足条件2,我们需要从最后一天开始往上更新即可

然后再正向更新一下,保证sum[i]>=sum[i-1]

最后代入公式即可。



#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)

typedef long long ll;
const int maxn = 100005;
const ll mod = 1e9+7;
const ll INF = 1e18;
const double eps = 1e-6;

int n;
ll a[maxn];
ll sum[maxn];

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%lld",&a[i]);
    ll now=0;
    for(int i=n-1;i>=0;i--)
    {
        now=max(now-1,a[i]+1);
        sum[i]=now;
    }
    ll ans=sum[0]-a[0]-1;
    for(int i=1;i<n;i++)
    {
        sum[i]=max(sum[i],sum[i-1]);
        ans+=(sum[i]-(a[i]+1));
    }
    printf("%lld\n",ans);
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值