P1884
要统计覆盖,而且不计重复,可以自然地想到差分后求前缀和的做法,并且此题数据范围较大,还需离散化。
我们定义结构体 Node 来存储每个矩形的左上角和右下角,
对于每次覆盖,我们只需对
#include <bits/stdc++.h>
using namespace std;
#define all(a) a.begin(), a.end()
#define debug(a) cout << a << "\n";
#define pb push_back
#define mp make_pair
#define mem(a, b) memset(a, b, sizeof(a))
#define endl "\n"
typedef long long ll;
typedef unsigned long long ull;
constexpr int MOD = 1e9 + 7;
constexpr int MAXN = 1e3 + 10;
struct Node
{
int X1, Y1, X2, Y2; // X1, Y1 是左上角,X2, Y2 是右下角
};
Node a[4 * MAXN];
int b[4 * MAXN], c[4 * MAXN], f[4 * MAXN][4 * MAXN];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, top = 0;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].X1 >> a[i].Y1 >> a[i].X2 >> a[i].Y2;
// 将点扔进 b 数组,方便离散化
b[++top] = a[i].X1;
b[++top] = a[i].Y1;
b[++top] = a[i].X2;
b[++top] = a[i].Y2;
}
sort(b + 1, b + top + 1);
b[0] = INT_MIN;
auto end = unique(b + 1, b + top + 1);
int new_top = distance(b, end) - 1;
for (int i = 1; i <= n; i++)
{
// 二分法离散化
a[i].X1 = lower_bound(b + 1, end, a[i].X1) - b;
a[i].Y1 = lower_bound(b + 1, end, a[i].Y1) - b;
a[i].X2 = lower_bound(b + 1, end, a[i].X2) - b;
a[i].Y2 = lower_bound(b + 1, end, a[i].Y2) - b;
}
for (int i = 1; i <= new_top; i++)
{
c[i] = b[i];
}
for (int i = 1; i <= n; i++)
{
for (int j = a[i].X1; j < a[i].X2; j++)
{
// 差分
f[j][a[i].Y1]++;
f[j][a[i].Y2]--;
}
}
for (int i = 1; i < new_top; i++)
{
for (int j = 1; j < new_top; j++)
{
f[i][j] += f[i][j - 1];
}
}
ll ans = 0;
for (int i = 1; i < new_top; i++)
{
for (int j = 1; j < new_top; j++)
{
if (f[i][j] != 0)
{
ans += (ll)(c[i + 1] - c[i]) * (c[j + 1] - c[j]); // 如果被覆盖过,计算面积
}
}
}
cout << ans;
return 0;
}