题目介绍
题目解读
题目很简单,求并区间面积
解题思路
离散化+二维差分
这种题用二维差分可以解决,但是问题在于x,y的值过大,而且还有负数,无法开数组进行差分
可以离散化处理x,y,再进行差分
离散化
离散化:把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:
原数据:1,999,100000,15;处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
处理后:{3,4},{2,6},{1,5};
(来自百度百科)
即使每个x,y都不相同,离散化后最多也就是N*4个数,完全可以进行差分解题
AC代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000;
int n;
int x1s[maxn + 1], y1s[maxn + 1], x2s[maxn + 1], y2s[maxn + 1]; //存储坐标
int G[4*maxn + 1][4*maxn + 1]; //二维差分数组
int arr[4 * maxn + 1], listInx = 0; //存储所有x,y的值
int rest[4 * maxn + 1],restInx = 0; //记录编号对应的数字
map<int, int> toId; //用于获得数字对应的编号
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> x1s[i] >> y1s[i] >> x2s[i] >> y2s[i];
arr[++listInx] = x1s[i]; //把坐标全添加到arr中
arr[++listInx] = y1s[i];
arr[++listInx] = x2s[i];
arr[++listInx] = y2s[i];
}
arr[0] = -1e9;
sort(arr + 1, arr + listInx + 1); //排序
for (int i = 1; i <= listInx; i++) {
if (arr[i] != arr[i - 1]) { //避免重复的值
rest[++restInx] = arr[i]; //编号restInx的值为arr[i];
toId[arr[i]] = restInx; //存进map 能够查询数值的编号
}
}
for (int i = 1; i <= n; ++i) {
int x1 = toId[x1s[i]]; //把x,y都换成对应的编号
int y1 = toId[y1s[i]];
int x2 = toId[x2s[i]];
int y2 = toId[y2s[i]];
G[x1][y2]++; //二维差分
G[x2][y2]--; //注意题目有写两个坐标的大小关系,注意选择合适的两个坐标中x和y
G[x1][y1]--;//这个题求的是点之间的面积,x,y并不需要-1,+1,具体请画图理解
G[x2][y1]++;
}
for (int i = 1; i <= restInx; i++) {
for (int j = 1; j <= restInx; j++) {
//得到每个点被覆盖的次数
G[i][j] += G[i - 1][j] + G[i][j - 1] - G[i - 1][j - 1];
}
}
long long ans = 0;
for (int i = 1; i <= restInx; i++) {
for (int j = 1; j <= restInx; j++) {
if (G[i][j] > 0) { //如果有被覆盖
//记得把编号还原为原来的坐标再计算
ans += (long) (rest[j + 1] - rest[j]) * (rest[i + 1] - rest[i]);
}
}
}
cout << ans << endl;
return 0;
}