![](https://i-blog.csdnimg.cn/blog_migrate/142fd985627aad3617ad4a75536dbdd7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/36e51e289a4dce8ce54ec2239f6165b5.png)
思路
- n条信息,每条信息有两个数据1 <= n <= 2x10^4,数据量很小,数据范围很大,我们可以考虑使用离散化将范围进行缩小
1、离散化
- 将使用到的a、b存储到vector中,存储完成进行去重,然后排序
- 将a、b存储到pair中,遍历每一个pair,通过二分找到原数据在vector中对应的下标
2、差分
- 将每一个pair中的 [a, b)区间进行加1,使用差分
3、进行前缀和
- 将差分数组进行前缀和
- 遍历前缀和之后的数组,如果当前下标中的值大于0,保存当前下标,继续往后遍历,直到遇到0,那么这个区间的实际长度为,第一次出现0的下标对应的原数据 - 第一次出现大于0下标对应的原数据
代码实现
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
typedef pair<int, int> PII;
int n;
vector<int> ans; // ans数组表示存储原数据
vector<PII> lr; // 存储每一个{a, b}
int find(int u)
{
int l = -1, r = ans.size(); // 二分找到u在ans中对应的下标
while(l + 1 != r)
{
int mid = l + r >> 1;
if(ans[mid] < u) l = mid;
else r = mid;
}
return r;
}
int main()
{
cin >> n;
while(n--)
{
int a, b;
cin >> a >> b;
ans.push_back(a), ans.push_back(b);
lr.push_back({a, b});
}
ans.erase(unique(ans.begin(), ans.end()), ans.end()); // 去重
sort(ans.begin(), ans.end()); // 排序
int res[ans.size() + 10]; // 差分数组
memset(res, 0, sizeof res);
for(int i = 0;i < lr.size();i ++)
{
PII p = lr[i];
int l = find(p.first), r = find(p.second); // 找到原数据离散化后对应的下标
res[l + 1] += 1; // 差分
res[r + 1] -= 1;
}
int cnt = 0; // 总长度
for(int i = 1; i <= ans.size(); i++)
{
res[i] += res[i-1]; // 前缀和
}
for(int i = 1;i <= ans.size();i ++) // 找到每一个区间的长度
{
int t = i;
while(res[i] > 0) i++;
cnt += (ans[i-1] - ans[t-1]);
}
cout << cnt << endl;
return 0;
}