Luogu5490 【模板】扫描线
https://www.luogu.com.cn/problem/P5490
扫描线
根据横坐标或纵坐标排序另一方向的线段,进入的赋值\(+1\),离开的赋值\(-1\)
注意一下,线段树的构造中,一个位置表示的是一个间隔,即\(a_1\)表示间隔\([1,2]\),间隔个数为点的个数\(-1\)
如果用点来建,一个点根本无法计算贡献
\(C++ Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define N 200005
using namespace std;
int x,y,_x,_y,n,cnt,cc;
int a1[N],a2[N],b1[N],b2[N],c[N];
ll ans;
struct node
{
int x,y,_y,t;
bool operator < (const node b) const
{
return x<b.x;
}
}w[N];
struct T
{
int cnt,len;
}t[N << 2];
void push_up(int p,int l,int r)
{
if (t[p].cnt)
t[p].len=c[r+1]-c[l]; else
if (l!=r)
t[p].len=t[p+p].len+t[p+p+1].len; else
t[p].len=0;
}
void add(int p,int l,int r,int x,int y,int z)
{
if (l>y || r<x)
return;
if (x<=l && r<=y)
{
t[p].cnt+=z;
push_up(p,l,r);
return;
}
int mid=(l+r) >> 1;
add(p+p,l,mid,x,y,z);
add(p+p+1,mid+1,r,x,y,z);
push_up(p,l,r);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&x,&y,&_x,&_y);
w[i+i-1].x=x;
w[i+i-1].y=y;
w[i+i-1]._y=_y;
w[i+i-1].t=1;
w[i+i].x=_x;
w[i+i].y=y;
w[i+i]._y=_y;
w[i+i].t=-1;
c[i+i-1]=_y,c[i+i]=y;
}
cnt=n << 1;
sort(c+1,c+cnt+1);
cc=unique(c+1,c+cnt+1)-c-1;
sort(w+1,w+cnt+1);
for (int i=1;i<=cnt;i++)
{
w[i].y=lower_bound(c+1,c+cc+1,w[i].y)-c;
w[i]._y=lower_bound(c+1,c+cc+1,w[i]._y)-c;
}
for (int i=1;i<cnt;i++)
{
add(1,1,cc,w[i].y,w[i]._y-1,w[i].t);
ans+=(ll)t[1].len*(w[i+1].x-w[i].x);
}
printf("%lld\n",ans);
return 0;
}