点相当于格,则先将右上角坐标x++, y++,将格转化成点。原问题等价于矩形面积并。
扫描线解决即可,枚举y扫描线,需要离散化x坐标轴。对于x坐标轴的离散化,需要将线段树原有的[l,r]闭区间转化成[l, r)左开右闭区间。这样每一点都代表一段区间V[r+1] - V[l]。
#include <bits/stdc++.h>
using namespace std;
#define all(x) x.begin(), x.end()
typedef long long LL;
const LL maxn = 3e5+10;
struct A {
LL l, r, h, f;
bool operator < (const A & b) const {
return h < b.h;
}
};
LL n;
vector<LL> V;
vector<A> seg;
LL getid(LL x) {
return lower_bound(all(V), x) - V.begin() + 1;
}
struct S {
LL sum, lazy;
} tr[maxn<<2];
LL pushup(LL l, LL r, LL rt) {
if(tr[rt].lazy) tr[rt].sum = V[r] - V[l-1];
else if(l == r) tr[rt].sum = 0;
else tr[rt].sum = tr[rt<<1].sum + tr[rt<<1|1].sum;
}
void update(LL L, LL R, LL c, LL l, LL r, LL rt) {
if(L <= l && R >= r) {
tr[rt].lazy += c;
pushup(l, r, rt);
return ;
}
LL m = (l + r) >> 1;
if(L <= m) update(L, R, c, l, m, rt<<1);
if(R > m) update(L, R, c, m+1, r, rt<<1|1);
pushup(l, r, rt);
}
int main() {
scanf("%lld", &n);
for(LL i = 1; i <= n; i++) {
LL x1, y1, x2, y2;
scanf("%lld%lld%lld%lld", &x1, &y1, &x2, &y2);
if(x1 > x2) swap(x1, x2);
if(y1 > y2) swap(y1, y2);
x2 ++, y2++;
V.push_back(x1), V.push_back(x2);
seg.push_back({x1, x2, y1, 1});
seg.push_back({x1, x2, y2, -1});
}
sort(all(seg));
sort(all(V));
V.erase(unique(all(V)), V.end());
LL ans = 0;
for(LL i = 0; i < seg.size() - 1; i++) {
LL l = getid(seg[i].l);
LL r = getid(seg[i].r) - 1;
LL h = seg[i+1].h - seg[i].h;
update(l, r, seg[i].f, 1, V.size(), 1);
// cout<<tr[1].sum<<" "<<h<<endl;
ans += tr[1].sum * h;
}
cout<<ans<<'\n';
return 0;
}