算法题(162):火烧赤壁
审题:
本题需要我们找到着火区域的总长度
思路:
方法一:离散化+差分首先我们分析题意:
一段区间是左闭右开的,所以着火区域是用右端点减去左端点。为了防止区间重叠导致的重复计算,我们需要使用差分的思想来解决问题,差分数组中每当有着火区域就让他索引位置+1,让末端位置-1。还原差分后最终的值不为0就是着火区域。
其次我们观察本题的数据范围,数据量并不大,但是数据范围很大,无法用值直接充当索引,这样会导致数组空间不够,所以我们先要对数据做离散化处理,以便后续可以根据离散值当索引将数据存进数组中
总体流程:
1.离散化处理数据
2.根据离散化的值建立差分数组
3.还原差分数组,确定真实着火区间
4.累加着火区间
解题:
#include<iostream> #include<algorithm> #include<unordered_map> using namespace std; const int N = 2e4 + 10; int n; int pos;//离散化后的数据个数 int a[N], b[N];//存储左右端点 int disc[2 * N];//离散化数据数组 unordered_map<int, int> m;//原始数据,离散值 int f[2 * N];//差分数组 int main() {cin >> n;//离散化处理for (int i = 1; i <= n; i++){cin >> a[i] >> b[i];disc[++pos] = a[i];disc[++pos] = b[i];}sort(disc + 1, disc + 1 + pos);//排序pos = unique(disc + 1, disc + 1 + pos) - (disc + 1);//去重for (int i = 1; i <= pos; i++){int x = disc[i];m[x] = i;}//差分数据for (int i = 1; i <= n; i++){int l = a[i];int r = b[i];f[m[l]]++; f[m[r]]--;}//还原差分数组for (int i = 1; i <= pos; i++){f[i] += f[i - 1];}//统计结果int answer = 0;for (int i = 1; i <= pos; i++){int j = i;while (j < pos && f[j] > 0) j++;answer = answer + disc[j] - disc[i];i = j;}cout << answer << endl;return 0; }
注意:
1.由于我们后面需要用到去重之后的离散化数组,所以在升序排序之后我们仍然需要对disc去重。2.哈希表是根据实际值查找离散值,disc数组是用离散值查找实际值。
哈希表用在差分数组部分,因为要对对应离散值位置进行着火判断。
disc用于映射找回实际着火区间,累加到answer中
P1496 火烧赤壁 - 洛谷