Codechef A temple of Snakes(思维)

点击打开链接

 题意

你想要为众蛇建造一座神殿。神殿将建在群山之中,可以将其视作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;
}
 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值