Codechef A temple of Snakes(思维)

来源:互联网 发布:淘宝用红包退款 编辑:程序博客网 时间:2024/05/22 08:48

点击打开链接

 题意

你想要为众蛇建造一座神殿。神殿将建在群山之中,可以将其视作n个块,其中第i个的高度为hi。神殿会建造在连续若干个块上,要求这些块的高度从1开始逐渐增加到某个高度,然后再逐渐减小到1,即,高度是形如1,2,3, ... ,x−1,x,x−1,x−2,...,1的序列。除了要建造神殿的块之外,其他块的高度都应该是0,以便人们从左右两侧看到神殿。

为了达成这一目标,你可以降低块的高度。一次操作中,你可以选择一块,并令其高度减小1。请求出最少需要进行多少次操作。

数据

输入的第一行包含一个整数 T,代表测试数据的组数。接下来是 T 组数据。每组数据的第一行包含一个整数n。接下来一行包含n个整数,其中第i个代表hi。

对于每组数据,输出一行,包含一个整数,代表最少需要的操作次数。

1<=T<=10, 2<=n<=1e5, 1<= hi<=1e9

输入

3

3

1 2 1

4

1 1 2 1

5

1 2 6 2 1

输出

0

1

3

说明

在第一组数据中,整座山已经符合要求。

在第二组数据中,将第 1 块的高度减小为 0,便可以在后 3 块上建造神殿。

在第三组数据中,可以将第 3 块的高度减小为 3。


思路(摘自Wannafly Union)

这道题的本质是求我们能留下来的最大的塔有多大,然后用总块数-用掉的块数就可以求出答案。我们考虑以每个点为中心,塔的左边能造多高。假设i号点最高能建h,那么i+1号点最高能建min(h+1,自身高度)。同理可求只考虑右边的情况。最后求个最值就可以了。

代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;typedef long long ll;const int maxn = 1e5+5;int a[maxn], l[maxn], r[maxn]; int main(void){    int t, n;    cin >> t;    while(t--)    {        memset(a, 0, sizeof(a));        memset(l, 0, sizeof(l));        memset(r, 0, sizeof(r));        scanf("%d", &n);        ll sum = 0;        for(int i = 1; i <= n; i++)            scanf("%d", &a[i]), sum += a[i];        for(int i = 1; i <= n; i++)            l[i] = min(a[i], l[i-1]+1);        for(int i = n; i >= 1; i--)            r[i] = min(a[i], r[i+1]+1);        ll ans = 0;        for(int i = 1; i <= n; i++)            ans = max(ans, (ll)min(l[i], r[i]));        printf("%lld\n", sum-(1+ans-1)*(ans-1)-ans);    }    return 0;} 


原创粉丝点击