分析:
扫描线乱搞
离散
Y
Y
坐标(保存在了数组里)
线段树的每一个结点维护的信息:
d
d
:区间内的块数
example:
00011100110 ---> d=2
00011111110 ---> d=1
:区间内的覆盖长度
s
s
: 区间是否被完全覆盖的标记
: 区间控制的是
Y[l]−Y[r]
Y
[
l
]
−
Y
[
r
]
,准确来说是
[Y[r+1]−Y[l]]
[
Y
[
r
+
1
]
−
Y
[
l
]
]
L,R
L
,
R
: 区间左右端点是否被覆盖
需要注意的就是update的时候,
如果一个结点被完全覆盖:t[bh].len=Y[t[bh].r+1]-Y[t[bh].l];
如果没有被完全覆盖:
t[bh].len=t[lc].len+t[rc].len;
t[bh].d=t[lc].d+t[rc].d-t[lc].R*t[rc].L;
注意到对于
l,r
l
,
r
的特殊定义:控制区间
[Y[r+1]−Y[l]]
[
Y
[
r
+
1
]
−
Y
[
l
]
]
所以我们要加入一个线段
a
a
的时候,虽然是
[Y[x],Y[y]]
[
Y
[
x
]
,
Y
[
y
]
]
范围上的
但是我们要直接
change(x,y−1)
c
h
a
n
g
e
(
x
,
y
−
1
)
Q.
l−r l − r 控制的是 [Y[r+1]−Y[l]] [ Y [ r + 1 ] − Y [ l ] ] ,这样维护是对的吗
A.
如果给出的边范围是
(1,3)
(
1
,
3
)
,离散后
Y[1]=1,Y[2]=2,Y[3]=3
Y
[
1
]
=
1
,
Y
[
2
]
=
2
,
Y
[
3
]
=
3
这条边的长度显然是
2=Y[3]−Y[1]
2
=
Y
[
3
]
−
Y
[
1
]
我们
change(1,2)
c
h
a
n
g
e
(
1
,
2
)
,最后在统计的时候长度就是:
Y[2+1]−Y[1]=2
Y
[
2
+
1
]
−
Y
[
1
]
=
2
没有任何问题
最后统计答案的时候想清楚就好
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=200005;
int n,tot=0,Y[N];
struct po{
int x,ya,yb,type;
};
po a[N];
struct node{
int d,len,s,l,r,L,R;
//d 区间内的块数
//len 区间覆盖长度
//s 区间覆盖标记
//l,r 区间控制的是Y[l]~Y[r]
//L,R 左右端点是否被覆盖
};
node t[N<<2];
int cmp(const po &A,const po &B) {return A.x<B.x||(A.x==B.x&&B.type<A.type);}
void update(int bh)
{
int lc=bh<<1;
int rc=bh<<1|1;
if (t[bh].s>0)
{
t[bh].len=Y[t[bh].r+1]-Y[t[bh].l];
t[bh].L=t[bh].R=1;
t[bh].d=1;
}
else if (t[bh].s<=0)
{
if (t[bh].l==t[bh].r)
{
t[bh].d=0; t[bh].len=0;
t[bh].L=t[bh].R=0;
} else {
t[bh].len=t[lc].len+t[rc].len;
t[bh].d=t[lc].d+t[rc].d-t[lc].R*t[rc].L;
t[bh].L=t[lc].L; t[bh].R=t[rc].R;
}
}
}
void build(int bh,int l,int r)
{
t[bh].d=0;
t[bh].len=0;
t[bh].s=0;
t[bh].l=l; t[bh].r=r;
t[bh].L=t[bh].R=0;
if (l==r) return;
int mid=(l+r)>>1;
build(bh<<1,l,mid);
build(bh<<1|1,mid+1,r);
}
void add(int bh,int l,int r,int z)
{
if (t[bh].l>=l&&t[bh].r<=r)
{
t[bh].s+=z; //覆盖标记
update(bh);
return;
}
int mid=(t[bh].l+t[bh].r)>>1;
if (l<=mid) add(bh<<1,l,r,z);
if (r>mid) add(bh<<1|1,l,r,z);
update(bh);
}
int main()
{
scanf("%d",&n);
int nn=0;
for (int i=1;i<=n;i++)
{
int xa,ya,xb,yb;
scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
tot++; Y[++nn]=ya;
a[tot].x=xa; a[tot].ya=ya; a[tot].yb=yb; a[tot].type=1;
tot++; Y[++nn]=yb;
a[tot].x=xb; a[tot].ya=ya; a[tot].yb=yb; a[tot].type=-1;
}
sort(Y+1,Y+nn+1);
nn=unique(Y+1,Y+1+nn)-Y-1;
sort(a+1,a+1+tot,cmp);
build(1,1,nn);
int x,y;
int ans=0,now_x=0,now_blo=0;
for (int i=1;i<=tot;i++)
{
x=lower_bound(Y+1,Y+1+nn,a[i].ya)-Y;
y=lower_bound(Y+1,Y+1+nn,a[i].yb)-Y;
add(1,x,y-1,a[i].type);
if (i>1) ans+=now_blo*2*(a[i].x-a[i-1].x);
ans+=abs(t[1].len-now_x);
now_x=t[1].len;
now_blo=t[1].d;
}
printf("%d",ans);
return 0;
}