算法 贪心+pair ——AcWing 2014.岛

题目

每当下雨时,农夫约翰的田地总是被洪水淹没。

由于田地不是完全水平的,所以一些地方充满水后,留下了许多被水隔开的“岛”。

约翰的田地被描述为由 N 个连续高度值 H1,…,HN 指定的一维场景。

假设该场景被无限高的围墙包围着,请考虑暴雨期间发生的情况:

最低处首先被水覆盖,形成一些不连贯的岛,随着水位的不断上升,这些岛最终都会被覆盖。

一旦水位等于一块田地的高度,那块田地就被认为位于水下。
在这里插入图片描述
上图显示了一个示例:在左图中,我们只加入了刚好超过 1 单位的水,此时剩下 4 个岛(最大岛屿剩余数量),而在右图中,我们共加入了 7 单位的水,此时仅剩下 2 个岛。

请计算,暴风雨期间我们能在某个时间点看到的最大岛屿数量。
水会一直上升到所有田地都在水下。

输入格式
第一行包含整数 N。

接下来 N 行,每行包含一个整数表示 Hi。

输出格式
输出暴风雨期间我们能在某个时间点看到的最大岛屿数量。

数据范围
1≤N≤105,
1≤Hi≤109

输入样例:

8
3
5
2
3
1
4
2
3

输出样例:

4

题解说明

思路
随着水位的上升,岛会根据岛高度由低到高的顺序逐一被水面覆盖,所以这里用贪心(枚举)方法对岛由低到高的进行枚举,枚举过程中对仍在水面上的岛的数量进行变动。
PS:
①对于水面每覆盖一个岛,一共有四种情况:
在这里插入图片描述

可以发现:只有当出现“中间高两侧低”状态时,岛屿数减1,当出现“中间低两侧高”时,岛屿数加1,其他情况岛屿数均不变。

代码

#include<iostream>
#include<cstring>
#include<algorithm>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 100010;

int n;
int h[N];//记录每座山的高度,用于枚举每个q时与相邻h对比
PII q[N];//q用于高度排序后枚举

int main(){
    
    
    
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &h[i]);

    n = unique(h + 1, h + n + 1 ) - h - 1;//判重得到  返回得到判重后的所有元素
    h[n + 1] = 0;
    
    //printf("n=%d\n",n);
    for(int i = 1; i <= n; i ++) q[i] = {
    
    h[i], i}; //将【每座岛的高度,下表序号】存入q
    
    sort(q + 1, q + n + 1);//排序
    
    int res = 1;//定义答案
    int cnt = 1;//定义当前岛数量
    
    for(int i = 1; i <= n; i++){
    
    
        int k = q[i].y;
        if(h[k -1] < h[k] && h[k + 1] < h[k]) cnt--;
        else if(h[k -1] > h[k] && h[k + 1] > h[k]) cnt++;
        
        if( q[i].x != q[i + 1].x)
            res = max(res, cnt);
        
    }
    printf("%d\n", res);
    
    return 0;
}

希望可以帮到你,欢迎点赞评论哦

猜你喜欢

转载自blog.csdn.net/smile66688/article/details/122993704
今日推荐