Acwing2014. 岛
Acwing2014. 岛
题目
每当下雨时,农夫约翰的田地总是被洪水淹没。
由于田地不是完全水平的,所以一些地方充满水后,留下了许多被水隔开的“岛”。
约翰的田地被描述为由 N 个连续高度值 H1,…,HN 指定的一维场景。
假设该场景被无限高的围墙包围着,请考虑暴雨期间发生的情况:
最低处首先被水覆盖,形成一些不连贯的岛,随着水位的不断上升,这些岛最终都会被覆盖。
一旦水位等于一块田地的高度,那块田地就被认为位于水下。

上图显示了一个示例:在左图中,我们只加入了刚好超过 11 单位的水,此时剩下 4 个岛(最大岛屿剩余数量),而在右图中,我们共加入了 7 单位的水,此时仅剩下 2 个岛。
请计算,暴风雨期间我们能在某个时间点看到的最大岛屿数量。
水会一直上升到所有田地都在水下。
输入格式
第一行包含整数 N。
接下来 N 行,每行包含一个整数表示 Hi。
输出格式
输出暴风雨期间我们能在某个时间点看到的最大岛屿数量。
数据范围
1≤N≤105,
1≤Hi≤109
输入样例:
8
3
5
2
3
1
4
2
3输出样例:
4为什么想到用差分(个人认为很重要)
y总讲4007. 非零段划分 - AcWing题库时并没有将题目和差分联系在一起,但在上一次ccf这道题没有做出来后,我意识到对差分的总结还不够深刻,于是进行了复盘
差分的2种应用方向
1.同时改变一个区间中数的大小
95%的差分都被应用到了这个方向,大部分人都很熟练
2.对差分数组本身意义的考察
差分数组中每个数表示:相邻两数之间的高度差,这个应用方向考察不多,相对陌生所以,难!
我是怎么注意到第二个方向的
这里要吹一下蓝书,蓝书上差分一共只有2道例题,这两道例题分别考察了这两个方向
4007. 非零段划分 - AcWing题库和本题2014. 岛 - AcWing题库其实都是101. 最高的牛 - AcWing题库的变形!!!
一维差分
| 题目链接 | 题意描述 | 题目总结 | c++题解 |
|---|---|---|---|
| 797. 差分 - AcWing题库 | 差分模板: 给一个区间所有数同时加上一个数; | 差分数组的每个数的前缀和就是原数 ;所以改变差分数组的一个数,所有求前缀和时用到这个数的都会受到影响 | |
| 100. 增减序列 - AcWing题库 | 每次给任意一个区间所有数+1或者-1,求多少次操作后,所有数相等; | 本题要理解差分数组本身的含义:表示原数组中每两个相邻数的差;将原数组都变成一样等价于将差分数组下标大于1的数都变为0;所以优先选择一对(正,负)操作 | AcWing 100. IncDec序列 - AcWing |
| 101. 最高的牛 - AcWing题库 | 已知数组中的最大数,和一些数之间的关系,求原数组每个数的最大可能值 | AcWing 101. 最高的牛 - AcWing | |
| 2014. 岛 - AcWing题库 | 同理,用map离散化优化高度的枚举(高度的数据范围大) | ||
| 4007. 非零段划分 - AcWing题库 | 已知数组中的每个数的值,和数组中的最大数,求一些数之间的关系 |
说明:
本题2014. 岛 - AcWing题库实际上的考察是:水位每上涨一个高度差后对数组中数的关系有怎样的影响
与101. 最高的牛 - AcWing题库相比相当于问:水位在哪里的时候有最多的长方形可以相互看见
思路
设一块长方形的高度为a[i],假设水从a[i-1]涨到(下降到)a[i],意味着所有高度在a[i]—a[i-1]的长方形都会被淹没(露出来),相当于这些长方形的高度差被抹平(产生)(对答案的贡献都减1(+1)).同时给一个区间减去(加上)一个数,用差分
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 500005,M = 10000;
int a[N],b[N];
int n;
int main()
{
cin >> n;
int res = 0;
for (int i = 1; i <= n; i ++ ){
cin >> a[i];
if(a[i]>a[i-1]){
//数的大小在[a[i-1],a[i]-1]之间的所有数都+1
b[a[i-1]]++,b[a[i]]--;
}
}
int sum = 0 ;
for (int i = 0; i <= M; i ++ ){
sum+=b[i];
res = max(res,sum);
}
cout << res;
}题解
对比4007. 非零段划分 - AcWing题库发现高度的数据范围比数量大的多余数想到了用map离散化(不能用unordered_map,unordered_map无法用来求前缀和)
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
typedef long long LL;
using namespace std;
const int N = 100005,M = 1e9+1;
int a[N];
map<int ,int >b;
int n;
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++ ){
cin >> a[i];
if(a[i]>a[i-1]){
//数的大小在[a[i-1],a[i]-1]之间的所有数大小都-1
b[a[i-1]]++,b[a[i]]--;
}
}
LL sum = 0 ,res = 0;
for (auto i:b ){
//求前缀和
sum+=i.second;
res = max(res,sum);
}
cout << res;
}