扫描线
扫描线
焯,我tm以为这玩意很高深,看了半天,tm很简单
核心就是我们要求一堆矩形的面积并or周长和,直接标记vis的话,我们的数组得开到 \(10^9 \times 10^9\)
但是我们发现,其实我们可以找一条竖直方向的线从左侧扫到右侧,那么我们就不需要考虑那么多了,我们只需要知道当前段是否为1,等于是把矩形拆成很多很多段,然后分别进行查询
我们发现每次我们等于是在进行区间加减操作,这个就很明显了吧,用线段树维护,每次查一下整个区间上有多少个点的 \(val > 0\),乘上横坐标长度即可
具体实现时,我们考虑用四元组 \(x_1,y_1,y_2,tag=1\) 和 \(x_2,y_1,y_2,tag=-1\) 来分别表示一个矩形的两个端点
我们进行离散化后直接用线段树维护线段长度
/*
BlackPink is the Revolution
light up the sky
Blackpink in your area
*/
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
#define int long long
#define rep(i, a, b) for (int i = (a); (i) <= (b); ++i)
#define per(i, a, b) for (int i = (a); (i) >= (b); --i)
#define whlie while
using namespace std;
const int N = 2e5 + 5;
const int mod = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> P;
namespace scan {
template <typename T>
inline void read(T& x) {
x = 0;
char c = getchar();
int f = 0;
for (; !isdigit(c); c = getchar())
f |= (c == '-');
for (; isdigit(c); c = getchar())
x = x * 10 + (c ^ 48);
if (f)
x = -x;
}
template <typename T, typename... Args>
inline void read(T& x, Args&... args) {
read(x), read(args...);
}
template <typename T>
inline void write(T x, char ch) {
if (x < 0)
putchar('-'), x = -x;
static short st[30], tp;
do
st[++tp] = x % 10, x /= 10;
while (x);
while (tp)
putchar(st[tp--] | 48);
putchar(ch);
}
template <typename T>
inline void write(T x) {
if (x < 0)
putchar('-'), x = -x;
static short st[30], tp;
do
st[++tp] = x % 10, x /= 10;
while (x);
while (tp)
putchar(st[tp--] | 48);
}
inline void write(char ch) {
putchar(ch);
}
} // namespace scan
using namespace scan;
int n, m, tot;
int a1, a2, b1, b2, res;
int Y[N];
struct node {
int l, r, x, mark;
bool operator<(node line2) {
return x < line2.x;
}
} line[N];
inline int lc(int p) {
return p << 1;
}
inline int rc(int p) {
return p << 1 | 1;
}
struct node2 {
int l, r, sum, tag;
} tr[N << 3];
inline void push_up(int p, int l, int r) {
if (tr[p].tag)
tr[p].sum = Y[r] - Y[l - 1];
else
tr[p].sum = tr[lc(p)].sum + tr[rc(p)].sum;
}
inline void update_tree(int p, int l, int r, int ql, int qr, int k) {
if (ql > r || qr < l)
return;
if (ql <= l && r <= qr) {
tr[p].tag += k;
push_up(p, l, r);
return;
}
int mid = (l + r) >> 1;
update_tree(lc(p), l, mid, ql, qr, k);
update_tree(rc(p), mid + 1, r, ql, qr, k);
push_up(p, l, r);
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
#endif
read(n);
rep(i, 1, n) {
read(a1, b1, a2, b2);
line[i] = (node){b1, b2, a1, 1};
line[i + n] = (node){b1, b2, a2, -1};
Y[i] = b1;
Y[i + n] = b2;
}
n <<= 1;
sort(Y + 1, Y + 1 + n);
tot = unique(Y + 1, Y + 1 + n) - (Y + 1);
rep(i, 1, n) {
line[i].l = lower_bound(Y + 1, Y + 1 + tot, line[i].l) - Y + 1;
line[i].r = lower_bound(Y + 1, Y + 1 + tot, line[i].r) - Y;
}
sort(line + 1, line + 1 + n);
rep(i, 1, n) {
res += 1ll * tr[1].sum * (line[i].x - line[i - 1].x);
update_tree(1, 1, tot, line[i].l, line[i].r, line[i].mark);
}
write(res, '\n');
return 0;
}
// write:RevolutionBP