51nod-【1276 岛屿的数量】

15 篇文章 0 订阅
题目来源:  Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 20  难度:3级算法题
 收藏
 关注
有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}。
Input
第1行:2个数N, Q中间用空格分隔,其中N为岛的数量,Q为查询的数量(1 <= N, Q <= 50000)。
第2 - N + 1行,每行1个数,对应N个岛屿的高度(1 <= A[i] <= 10^9)。
第N + 2 - N + Q + 1行,每行一个数,对应查询的海平面高度(1 <= Q[i] <= 10^9)。
Output
输出共Q行,对应每个查询的岛屿数量。
Input示例
5 4
2
1
3
2
3
0
1
3
2
Output示例
1
2
0

2

我感觉这一题有2个难点;1、如何解决超时问题,2、sum=1;之后为什么

后面一直用这个值(我在开始写的时候不懂为什么每次出循环的时候,为什么

不再次把sum=1);

这个题目有q次询问,我们不必每次询问就给出一个答案,可以最后输出q个

答案;

对于每一个查询 u;它将淹没h<=u的陆地;我们对每一h<=u的陆地进行处理

如果  h的左边的陆地可以被淹没,右边的也可以淹没那sum--;

if h左边和右边都没有被淹没,sum++

对于边界特殊考虑一下就行了

开始解释第2个问题:其实我们按照从小到大顺序排列,u的值将淹没所有

小于等于u的h,我们可以直接一个个找(这样比较浪费时间);因为前面

小于u的已经算出来了,我们就可以在它们的基础上进行操作还是一样的

(不懂得好好想想,表达不清楚的地方请忍耐一下)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
	int h;
	int pos;
}arr[51000];
int ans[51000],visited[51000]={0};
struct node2
{
	int h2;
	int pos2;
}arr2[51000];
bool cmp(node a,node b)
{
	return a.h<b.h;
}
bool cmp2(node2 a,node2 b)
{
	return a.h2<b.h2;
} 
int main()
{
	int n,q;
	scanf("%d%d",&n,&q);
	int i;
	for(i=0;i<n;++i)
	{
		scanf("%d",&arr[i].h);
		arr[i].pos=i;//记录每一个点的位置 
	} 
	sort(arr,arr+n,cmp);
	for(i=0;i<q;++i)
	{
		scanf("%d",&arr2[i].h2);
		arr2[i].pos2=i;//记录输出顺序 
	}
	sort(arr2,arr2+q,cmp2);
	int j=0,sum=1;
	for(i=0;i<q;++i)
	{
		for(;j<n;++j)
		{
			if(arr2[i].h2>=arr[j].h)
			{
				visited[arr[j].pos]=1;
				if(arr[j].pos==0)
				{
					if(visited[arr[j].pos+1]) 
						--sum;
					continue;
				} 
				if(arr[j].pos==n-1)
				{
					if(visited[arr[j].pos-1]) 
						--sum;
					continue;
				} 
				if(visited[arr[j].pos+1]&&visited[arr[j].pos-1])
					--sum;
				if(!visited[arr[j].pos+1]&&!visited[arr[j].pos-1])
					++sum; 
			} 
			else
				break;
		}
		ans[arr2[i].pos2]=sum;//重点理解一下,sum的值没有再次
		//变成 1 
	}
	for(i=0;i<q;++i)
		printf("%d\n",ans[i]); 
	return 0;
} 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值