P5490 【模板】扫描线
P5490 【模板】扫描线
我们建立一棵线段树 将一个节点管辖一个区间 相当于 \((l,r)\) 的节点管辖的是 \(l,r+1\) 的两个坐标值
这里不用打标记的原因是 如果你覆盖了一个区间 那么对于所有子区间的覆盖都是没有意义的(因为是区间并) 所以不会造成错误
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define mid (l+r>>1)
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define int long long
const int N = 1e6 + 5;
//char buf[1<<24] , *p1 , *p2;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int n , sz , xx[N] , ans;
struct line { int l , r , h , add; } a[N];
struct tree
{
struct node { int sum , len; } t[N<<2];
inl void up ( int p , int l , int r )
{
if ( t[p].sum ) t[p].len = xx[r+1] - xx[l];
else t[p].len = t[ls].len + t[rs].len;
}
void upd ( int p , int l , int r , int x , int y , int val )
{
if ( xx[r+1] <= x || xx[l] >= y ) return;
if ( x <= xx[l] && xx[r+1] <= y )
{
t[p].sum += val , up(p,l,r);
return;
}
upd ( lson , x , y , val );
upd ( rson , x , y , val );
up(p,l,r);
}
}T;
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
n = read();
for ( int i = 1 ; i <= n ; i ++ )
{
int xx1 = read() , yy1 = read() , xx2 = read() , yy2 = read();
xx[i*2-1] = xx1 , xx[i*2] = xx2;
a[i*2-1] = { xx1 , xx2 , yy1 , 1 };
a[i*2] = { xx1 , xx2 , yy2 , -1 };
}
n <<= 1;
sort ( a + 1 , a + n + 1 , [](const line &a , const line &b) { return a.h < b.h; } );
sort ( xx + 1 , xx + n + 1 );
int tot = unique ( xx + 1 , xx + n + 1 ) - xx - 1;
for ( int i = 1 ; i < n ; i ++ )
{
T.upd ( 1 , 1 , tot - 1 , a[i].l , a[i].r , a[i].add );
ans += T.t[1].len * ( a[i+1].h - a[i].h );
}
cout << ans << endl;
return 0;
}