Limak is a little bear who loves to play. Today he is playing by destroying block towers. He built n towers in a row. The i-th tower is made of hi identical blocks. For clarification see picture for the first sample.
Limak will repeat the following operation till everything is destroyed.
Block is called internal if it has all four neighbors, i.e. it has each side (top, left, down and right) adjacent to other block or to the floor. Otherwise, block is boundary. In one operation Limak destroys all boundary blocks. His paws are very fast and he destroys all those blocks at the same time.
Limak is ready to start. You task is to count how many operations will it take him to destroy all towers.
The first line contains single integer n (1 ≤ n ≤ 105).
The second line contains n space-separated integers h1, h2, ..., hn (1 ≤ hi ≤ 109) — sizes of towers.
Print the number of operations needed to destroy all towers.
6 2 1 4 6 2 2
3
7 3 3 3 1 3 3 3
2
The picture below shows all three operations for the first sample test. Each time boundary blocks are marked with red color.
题目大意:
给你一个长度为N的一串序列,ai表示在这个位子上有一座高度为ai的木块。
每次操作需要去掉所有这样的木块:
一个木块如果上下左右有一个空白位子。
问一共需要操作几次,使得整个序列变成空的。
思路(思路源自:http://blog.csdn.net/nike0good/article/details/48103631):
找最长的1 2 3 4 3 2 1这样的序列。
因为我们每一轮操作一定会使得一整个序列的最左边和最右边的两个序列直接变成0。
所以我们无论是很大的数还是很小的数,我们只要找到类似1 2 3 4 3 2 1这样的序列即可。
那么O(n)维护一个数组l【i】,表示以i为山峰顶端点的话,其左边能够撑住多少次操作。
同理O(n)维护一个数组r【i】,表示以i为山峰顶端点的话,其右边能够撑住多少次操作。
那么最终O(n)枚举这个山峰顶点,其以i为山峰顶点的话,其能够撑住的操作次数为:min(l【i】,r【i】);
那么过程维护一个最大值即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int a[105000];
int l[105000];
int r[105000];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
a[0]=0;a[n+1]=0;
l[0]=0;l[n+1]=0;
r[0]=0;r[n+1]=0;
for(int i=1;i<=n;i++)l[i]=min(l[i-1]+1,a[i]);
for(int i=n;i>=1;i--)r[i]=min(r[i+1]+1,a[i]);
int output=0;
for(int i=1;i<=n;i++)
{
output=max(output,min(l[i],r[i]));
}
printf("%d\n",output);
}
}