51nod 1276 1276 岛屿的数量 (很好玩的题目

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1276 1276 岛屿的数量 (很好玩的题目相关的知识,希望对你有一定的参考价值。

题意:

有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

 

这个题目用了一些小技巧 

可以看作1-n周围的已经被淹没 cnt = 2;

那么 cnt -1 就是答案

当一个岛被淹没 如果他的左右有一块被淹没的区域 那么cnt不变

当周围没被淹 那么cnt++

如果周围都被淹没 那么淹没的区域为cnt--

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<climits>
#include<vector> 
using namespace std;
const int N = 5e4+10;
int min_h = INT_MAX,max_h = INT_MIN;
struct data
{
    int h,id;   /* data */
}Q[N];
bool vis[N];
vector<int>v[N],num;
int H[N];
int ans[N];
int getid(int x)
{
    x++;
    return lower_bound(num.begin(),num.end(),x)-num.begin()-1; 
}
bool cmp(data a,data b)
{
    return a.h<b.h;
}
int cnt = 2;
void check(int pos)
{
    vis[pos] = true;
    if(vis[pos+1]&&vis[pos-1])
    {
        cnt--;
    }
    else{
        if(vis[pos+1]||vis[pos-1])
        {
            ;
        }
        else{
            cnt++;
        }
    }
}
int main()
{
    int n,q,t;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&t);
        num.push_back(t);
        H[i] = t;
        max_h = max(max_h,t);
        min_h = min(min_h,t);
    }
    sort(num.begin(),num.end());
    num.erase(unique(num.begin(),num.end()),num.end() );
    for(int i=1;i<=n;i++)
    {
        //cout<<getid(H[i])<<endl;
        v[getid(H[i])].push_back(i);
    }
    vis[0] = vis[n+1] = true;
    
    for(int i=0;i<q;i++)
    {
        scanf("%d",&Q[i].h);
        Q[i].id = i;
    }
    sort(Q,Q+q,cmp);
    int pre = -1;
    for(int i=0;i<q;i++)
    {
        if(Q[i].h>=max_h)
        {
            ans[Q[i].id] = 0;
            continue;
        }
        if(Q[i].h<min_h)
        {
            ans[Q[i].id] = 1;
            continue;
        }
        int now = getid(Q[i].h);
        //cout<<endl<<"H: "<<Q[i].h<<" id:  "<<now<<endl;
        for(int j = pre+1;j<=now;j++)
        {
            int len = v[j].size();
            for(int k=0;k<len;k++)
            {
                check(v[j][k]);
               //cout<<v[j][k]<<"  ";
            }
        }
        pre = now;
        ans[Q[i].id] = cnt - 1;
    }
    for(int i=0;i<q;i++)
    {
        printf("%d\\n",ans[i]);
    }
    return 0;
}
AC代码

 

以上是关于51nod 1276 1276 岛屿的数量 (很好玩的题目的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1276 岛屿的数量

51nod1276(xjb)

51nod 1276 一个标签是并查集但跟并查集没有关系的3级题

poj 1276(多重背包+最接近)

hdu1276STL链表的应用

poj1276--Cash Machine--多重背包