nkoj 1279
Description
每当下雨时,FJ的牧场都会进水。由于牧场地面高低不平,被水淹没的地方不是很统一,形成一些岛屿。
FJ的牧场可描述成一个一维的地形图,由N(1 <= N <= 100,000)个彼此相连的柱状的高度值组成。高度值为H(1)...H(n),(1 <= H(i) <= 1,000,000,000) 。假定这个地形图的两端有两条无限高的墙围着。
当雨一直下时,地形图上最低的区域先被水淹没,形成一些不相邻的岛屿。一旦水面高度到达一个区域的高度,则认为这个区域被淹没。
左图,在当前水面时,有4个岛屿。右图,在水面升高后,剩下2个岛屿。显然,最终所有的区域都会沉入水面。
算出当雨从开始下到最后所有岛屿沉入水中,最多时可形成多少个岛屿。
分析:
离散化排序处理后,逐个淹没,对每一个建筑:
如果两边的建筑都被淹没,则该建筑被淹没后岛屿消失,ans--;
如果只有一边被淹没,岛屿只是变小,ans不变;
如果两边都没有被淹没,该岛屿被一分为二,ans++;
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
bool sink[100005]; //标记i号建筑是否被淹没
struct land{
int h,id; //h表示高度,id表示排序前的序号
bool operator < (const land &a)const{
return h<a.h;
}
}s[100005];
int main(){
int n,i,k,j,ans=1,cur=1;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&s[i].h);
s[i].id=i;
}
sort(s+1,s+1+n);
sink[0]=sink[n+1]=true;
for(i=j=1;i<=n;i++){
while(s[j].h==s[i].h){ //注意处理相同高度的情况
sink[s[j].id]=true;
if(sink[s[j].id-1]&&sink[s[j].id+1])cur--; //两边都被淹没了,该岛屿消失
else if(!sink[s[j].id-1]&&!sink[s[j].id+1])cur++; //两边都没淹没,岛屿一分为二
j++;
}
ans=max(ans,cur); //更新答案
}
printf("%d",ans);
}