[CodeForces 573B] Bear and Blocks (脑洞题)

CodeForces - 573B
一列上有若干个方块堆,每堆方块有一个高度
每次可以消去这堆方块最外面的那层,问要几次才能消去
这是个脑洞题,还是有点难度的

首先可以预见的是
1) 每堆方块每次至少可以消去最顶上的一个
2) 每堆方块消去后,将与左右相邻中最矮的同高,如果都比他高,他就只能向下消一个
3) 每次都能消掉最左和最右两列

然而实际上这题从两边同时开始考虑消去的话,比较复杂
不妨只设他消去的规则只受他一边的限制,例如左边
这样从左到右考虑一次,从右到左考虑一次,再对两次取 min
就能算出某堆方块消去的次数
这是这题思维的突破口

从左到右考虑
首先最开始处于最左边的方块堆肯定一下子就消掉了
而后面的方块也不过是跟随其左边的脚步
左边都消去后,他才裸露出来,再用一次才能消去
除非中间方块很矮,还没等他裸露成最左的方块,他就自己一个一个地消没了
他消没了以后,他右边的方块就成为了裸露出来的边缘方块

所以事实上,处于右边的方块若不是自行逐个消去
就依赖于处于其左边的方块消去,将其暴露成边缘方块

所以设 res[i]为 第i堆消去所用次数
res[i] = min( res[i-1]+1, inpt[i] )
从右到左类似,然后答案再在其中取 max

时间复杂度 O(n)

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Pow2(a) (a*a)

const int maxn=1e5+10;
int N,ans;
int inpt[maxn];
int res[maxn][2];

int main()
{
    scanf("%d", &N);
    for(int i=1; i<=N; i++) scanf("%d", &inpt[i]);
    for(int i=1; i<=N; i++) res[i][0]=min(inpt[i],res[i-1][0]+1);
    for(int i=N; i>=1; i--) res[i][1]=min(inpt[i],res[i+1][1]+1);
    for(int i=1; i<=N; i++) ans=max(ans,min(res[i][0],res[i][1]));
    printf("%d\n", ans);
    return 0;
}

你可能感兴趣的:(codeforces)