概述
Picture
题目链接:HDU - 1828
题意:有多个矩形重叠在一起,求出重叠后的图形的周长,如下图,阴影部分是若干矩形重叠后的部分,彩色线条是重叠后图形的边框,即周长,左侧是矩形的坐标:
当我们用扫描线由下向上扫的时候每次变化的长度之后就是上下底线的长度之后,然后就剩下竖线的长度和了;
竖线的长度和是扫描线移动长度*竖线条数;移动长度就是上下两根线间隔,关键是求条数;
我们用线段树维护时,[l, r]区间的竖线条数分三种情况:
一:[l, r]被完全覆盖,此时由且只有2条竖线;
二:l=r此时是叶节点为0;
三:[l, r]被覆盖部分,那么此区间的竖线条数是子区间竖线条数之和,但是当左子区间的右边与由区间的左边重叠时,父区间竖线条数要减少两条;
用由下向上的扫描线是正确的,但是改成由左到右的扫描线就WA了,一直不明所以,若有朋友了解望指出!
#include <bits/stdc++.h>
using namespace std;
const int maxn=100010;
struct Line{
int y, x1, x2, v;
Line(){}
Line(int y0, int x10, int x20, int v0){
y=y0, x1=x10, x2=x20, v=v0;
}
bool operator < (const Line &p) const{
return y<p.y;
}
}line[maxn];
struct node{
int l, r, v, len, s, ls, rs;
}tr[maxn<<3];
void build(int m, int l, int r){
tr[m].l=l;
tr[m].r=r;
tr[m].len=tr[m].v=tr[m].s=tr[m].ls=tr[m].rs=0;
if(l==r) return;
int mid=(l+r)>>1;
build(m<<1, l, mid);
build(m<<1|1, mid+1, r);
}
void pushup(int m){
if(tr[m].v){
tr[m].len=tr[m].r+1-tr[m].l;
tr[m].s=1;
tr[m].ls=tr[m].rs=1;
}else if(tr[m].l==tr[m].r){
tr[m].len=tr[m].s=tr[m].ls=tr[m].rs=0;
}else{
tr[m].len=tr[m<<1].len+tr[m<<1|1].len;
tr[m].ls=tr[m<<1].ls;
tr[m].rs=tr[m<<1|1].rs;
tr[m].s=tr[m<<1].s+tr[m<<1|1].s-(tr[m<<1].rs&tr[m<<1|1].ls);
}
}
void updata(int m, int l, int r, int v){
if(tr[m].l==tr[m].r){
tr[m].v+=v;
pushup(m);
return;
}
int mid=(tr[m].r+tr[m].l)>>1;
if(r<=mid) updata(m<<1, l, r, v);
else if(l>mid) updata(m<<1|1, l, r, v);
else{
updata(m<<1, l, mid, v);
updata(m<<1|1, mid+1, r, v);
}
pushup(m);
}
int
main(){
int n, x1, x2, y1, y2;
while(~scanf("%d", &n)){
if(n==0){
printf("0n");
continue;
}
int L=maxn, R=-maxn, cnt=0;
for(int i=0; i<n; i++){
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
line[++cnt]=Line(y1, x1, x2, 1);
line[++cnt]=Line(y2, x1, x2, -1);
L=min(L, x1);
R=max(R, x2);
}
build(1, L, R);
sort(line+1, line+1+cnt);
int ans=0, prelen=0;
for(int i=1; i<=cnt; i++){
int l=line[i].x1, r=line[i].x2-1, v=line[i].v;
updata(1, l, r, v);
ans+=abs(prelen-tr[1].len);
prelen=tr[1].len;
if(i!=cnt) ans+=2*tr[1].s*(line[i+1].y-line[i].y);
}
printf("%dn", ans);
}
return 0;
}
最后
以上就是迷你白猫为你收集整理的Picture HDU - 1828(线段树,扫描线)的全部内容,希望文章能够帮你解决Picture HDU - 1828(线段树,扫描线)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复