有N个岛连在一起形成了一个大的岛屿,如果海平面上升超过某些岛的高度时,则这个岛会被淹没。原本的大岛屿则会分为多个小岛屿,如果海平面一直上升,则所有岛都会被淹没在水下。
给出N个岛的高度。然后有Q个查询,每个查询给出一个海平面的高度H,问当海平面高度达到H时,海上共有多少个岛屿。例如:
岛屿的高度为:{2, 1, 3, 2, 3}, 查询为:{0, 1, 3, 2}。
当海面高度为0时,所有的岛形成了1个岛屿。
当海面高度为1时,岛1会被淹没,总共有2个岛屿{2} {3, 2, 3}。
当海面高度为3时,所有岛都会被淹没,总共0个岛屿。
当海面高度为2时,岛0, 1, 3会被淹没,总共有2个岛屿{3} {3}。
第2 - N + 1行,每行1个数,对应N个岛屿的高度(1 <= A i i <= 10^9)。
第N + 2 - N + Q + 1行,每行一个数,对应查询的海平面高度(1 <= Q i i <= 10^9)。
5 4 2 1 3 2 3 0 1 3 2
1 2 0 2
这个题需要用两个结构体,第一个存岛屿的高度,和岛屿的位置,后面用sortr按岛屿高度从小到大排序。第二个存查询高度,和查询的先后,再用sort按查询高度从小到大排序(这个大大减少的时间空间的复杂度)。如果按照这样排序,我们可以从小到大,查询一遍即可(已经查询过的就不需要在查了)(真的很难想到)。
在介绍岛屿怎么样是连成的,我们对这些岛进行处理的时候处理两种情况:第一种就是多了一片岛屿,第二种就是少了一片岛屿,对应第一种情况,如果当前去掉的这个岛屿的两边都是岛屿,那么才能多一片岛屿,对于第二种情况,如果当前去掉的这个岛屿的两边都是水了,我们才能少了一片岛屿。在结构中我们存入的有这些岛屿的位置,怎样判断是水还是岛屿?我们需要从新开一个数组book,用来标记,(切记初始化的时候,只需要把岛屿位置当作下标,标记为1,其余的都为0)我们在查询时,发现有淹的岛屿,需要把他标记为0,就这么多,代码奉上。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std ;
#define maxt 500000+10
int book[maxt];
int a[maxt];
struct note1
{
int a;
int b;
} Q[maxt];
struct note2
{
int x;
int y;
} q[maxt];
bool cmp1(note1 t1,note1 t2)
{
return t1.a<t2.a;
}
bool cmp2(note2 t1,note2 t2)
{
return t1.x<t2.x;
}
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m))
{
memset(book,0,sizeof(book));
for(int i=1; i<=n; i++)
{
scanf("%d",&Q[i].a);
book[i]=1;
Q[i].b=i;
}
sort(Q+1,Q+n+1,cmp1);
for(int j=1; j<=m; j++)
{
scanf("%d",&q[j].x);
q[j].y=j;
}
sort(q+1,q+m+1,cmp2);
int maxn=0,cont=1,j=1;
for(int i=1; i<=m; i++)
{
if(q[i].x<=maxn)
{
a[q[i].y]=cont;
}
else
{
maxn=q[i].x;
while(j<=n&&Q[j].a<=q[i].x)
{
if(book[Q[j].b]&&book[Q[j].b+1]&&book[Q[j].b-1]) cont++;
if(book[Q[j].b]&&!book[Q[j].b+1]&&!book[Q[j].b-1])cont--;
book[Q[j].b]=0;
j++;
}
a[q[i].y]=cont;
}
}
for(int i=1; i<=m; i++)
printf("%d\n",a[i]);
}
return 0;
}