计算畸形区域的周长
比面积的扫描要麻烦些,原因就在不重叠区域的处理,同一段高度可能要重复叠加
所以线段树的结点里要多维护三个东西:
times:区间里不重叠的区间数
比如说第一个区间是1~5,第二个是2~6,,第三个是9~10,那前两个可以合成1~6,和第三个独立,则这个整体的times为2
为了维护times,我们需要lbd和rbd两个变量,分别作为区间左右端点是否被覆盖的标志
有的博客里把这两个变量写成了bool型,这些其实不好,在运算时会带来麻烦,我们直接用int 0和1表示会好些。这样只有在左孩子的rbd*右孩子的lbd!=0的时候才表示两孩子连接时会多一个覆盖次数
感觉扫描线的题目最关键的就是即使把更新后的影响传递上去
还有一个比较关键的东西就是离散化的理解
我的离散化是:把每一个x及其与下一个x之间的区间看作一个整体
比如1 5 8三个点
离散化后,1表示1~5,2表示5~8
应该可以注意到,只需要离散n-1个点,因为最后一个点的右边是没有长度的
所以当线段树中一个结点的表示区间是1~2,那这个区间的长度应该是1~8(1~5+5~8)
具体看代码
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include"cstring" #include"queue" #include"map" #include"set" #include"vector" #define ll long long #define mems(a,b) memset(a,b,sizeof(a)) #define ls pos<<1 #define rs pos<<1|1 using namespace std; const int MAXN = 1e5+50; const int MAXQ = 10050; const int INF = 0x3f3f3f3f; int n,m; int x[MAXN]; struct Line{ int l,r,h,w; Line(){} Line(int a,int b,int c,int d):l(a),r(b),h(c),w(d){} }line[MAXN]; bool cmp(Line a,Line b){ return a.h<b.h; } struct Node{ int l,r; int len; int cnt; int times; int w; int lbd,rbd; }node[MAXN<<2]; void build(int l,int r,int pos){ node[pos].l=l; node[pos].r=r; node[pos].cnt=node[pos].w=node[pos].times=0; node[pos].lbd=node[pos].rbd=0; node[pos].len=x[node[pos].r+1]-x[node[pos].l]; if(l==r) return; int mid=(l+r)>>1; build(l,mid,ls); build(mid+1,r,rs); } void pushup(int pos){ if(node[pos].w>0){ node[pos].cnt=node[pos].len; node[pos].lbd=node[pos].rbd=node[pos].times=1; } else if(node[pos].l==node[pos].r){ node[pos].cnt=0; node[pos].lbd=node[pos].rbd=node[pos].times=0; } else{ node[pos].cnt=node[ls].cnt+node[rs].cnt; node[pos].lbd=node[ls].lbd; node[pos].rbd=node[rs].rbd; node[pos].times=node[ls].times+node[rs].times-node[rs].lbd*node[ls].rbd; } } int get_pos(int w){ int low=0,high=m,mid,ans; while(low<=high){ mid=(low+high)>>1; if(x[mid]==w) return mid; else if(x[mid]>w) high=mid-1; else low=mid+1; } } void update(int l,int r,int pos,int w){ if(l<=node[pos].l&&node[pos].r<=r){ node[pos].w+=w; pushup(pos); return; } int mid=(node[pos].l+node[pos].r)>>1; if(l<=mid) update(l,r,ls,w); if(r>mid) update(l,r,rs,w); pushup(pos); } int main(){ //freopen("in.txt","r",stdin); while(~scanf("%d",&n)){ for(int i=0;i<2*n;i+=2){ int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); line[i]=Line(x1,x2,y1,1); line[i+1]=Line(x1,x2,y2,-1); x[i]=x1; x[i+1]=x2; } sort(line,line+2*n,cmp); sort(x,x+2*n); m=0; for(int i=1;i<2*n;i++) if(x[i]!=x[i-1]) x[++m]=x[i]; build(0,m-1,1); int ans=0; int pre=0; for(int i=0;i<2*n-1;i++){ int l=get_pos(line[i].l); int r=get_pos(line[i].r)-1; update(l,r,1,line[i].w); ans+=2*node[1].times*(line[i+1].h-line[i].h); ans+=abs(node[1].cnt-pre); pre=node[1].cnt; } ans+=line[2*n-1].r-line[2*n-1].l; printf("%d\n",ans); } return 0; }