有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 02
我感觉这一题有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; }