扫描线
线段树维护扫描线的长度--求矩形面积
https://www.luogu.com.cn/record/83280051
注意的就是(1)线段树一个节点代表单位线段,tot不加进去(2)懒度标记优化,用sum记录整条线段的覆盖次数,有就让len=sum_len,没有就用儿子的(3)lenth=M[r+1]-M[l],因为一条线段i的长度是M[i+1]-M[i]
int n,cnt,M[MAXN<<1];
struct Line
{
ll l,r,h;
int mark;
bool operator<(const Line&gh)const
{
return h<gh.h;
}
Line(){}
Line(ll wc1,ll wc2,ll wc3,int mar)
{
l=wc1,r=wc2,h=wc3;mark=mar;
}
}e[MAXN<<1];
struct Segtree
{
int ls,rs,sum;ll len;
}t[MAXN<<2];
int root,tot ;
#define lson t[rt].ls
#define rson t[rt].rs
inline void Build(int&rt,int l,int r)
{
if(!rt)rt=++tot;
if(l==r)return;
int mid=(l+r)>>1;
Build(lson,l,mid);Build(rson,mid+1,r);
}
inline void Pushup(int rt,int l,int r)
{
if(t[rt].sum)
{
t[rt].len=M[r+1]-M[l];
}
else
{
t[rt].len=t[lson].len+t[rson].len;
}
}
inline void Insert(int rt,int l,int r,int L,int R,int mak)
{
if(R<=M[l]||L>=M[r+1])return;//没关系
if(L<=M[l]&&M[r+1]<=R)
{
t[rt].sum+=mak;
Pushup(rt,l,r);return;
}
int mid=(l+r)>>1;
Insert(lson,l,mid,L,R,mak);
Insert(rson,mid+1,r,L,R,mak);
Pushup(rt,l,r);
}
int main()
{
//freopen("A_big_sample.in","r",stdin);
// freopen("dfs.txt","w",stdout);
n=re();
_f(i,1,n)
{
ll w1=re(),w2=re(),w3=re(),w4=re();//x1 y1 x2 y2
e[i<<1]=Line(w1,w3,w2,1);
e[(i<<1)-1]=Line(w1,w3,w4,-1);
M[++cnt]=w1,M[++cnt]=w3;
}
n<<=1;
sort(e+1,e+1+n);
sort(M+1,M+1+cnt);
int num=unique(M+1,M+1+cnt)-M-1;
Build(root,1,num-1);//是说忽略掉num+1,因为是线段
ll sd=0;
_f(i,1,n-1)//代表线段
{
//chu("insert():%lld--%lld\n",e[i].l,e[i].r);
Insert(root,1,num-1,e[i].l,e[i].r,e[i].mark);
sd+=(t[root].len)*(e[i+1].h-e[i].h);
}
chu("%lld",sd);
return 0;
}