pku1177 Picture
思路:
1,对y坐标离散化,设有ycnt个不同的y值,在[0,ycnt]上建立线段树
2,建立竖边结构(每个矩形有两条竖边,n个矩形有2*n条竖边):
struct Edge{
int yu;//竖边上端点y坐标
int yd;//下端点y坐标
int x;//x坐标
int tag;//竖边类型
}
把所有竖边分为IN和OUT两类,再对x排序,扫描线遇到IN则对线段树插入[yd,yu],遇到OUT则删除[yd,yu],注意只有曾经插入过的区间才能够进行删除
3,说说线段树的结点:
struct Node{
int l,r;//区间
int cnt;//计数器
int nseg,nlen;//扫描线被矩形覆盖的部分的段数和长度
bool lc,rc;//若该区间左右端点是否被覆盖的标记
}
设xans和yans分别为竖轮廓和横轮廓的长度,root'和root分别记录了扫描线在位置x1和x2时区间[0,ycnt]的信息,若扫描线从x1扫描至x2,则xans和yans有如下变化:
xans+=root'.nseg*2*(x2-x1);
yans+=abs(root.nlen-root'.nlen);
另外,在插入和删除操作中要注意对线段树结点信息的维护
#include <iostream>
#include <algorithm>
using namespace std;
#define IN 1
#define OUT 0
#define MAXN 10001
#define clr(x) memset(x,0,sizeof(x));
int n,ycnt,yinterval[2*MAXN],yans,xans;
//yinterval[i]=y表示纵坐标经过排序后第i个不同的纵坐标为y
int sy[2*MAXN];
//sy[y]=i表示纵坐标经过排序后y是第i小的纵坐标,与yinterval[i]=y互为反函数
struct Edge{
int yu,yd,x,tag;
}e[2*MAXN];
struct Node{
int l,r;
int cnt;
int nseg,nlen;
bool lc,rc;
}nod[3*MAXN];
class CP{
public:
int operator()(Edge &arg1,Edge &arg2){
return arg1.x<arg2.x;
}
};
void buildtree(int v,int l,int r){
nod[v].l=l;
nod[v].r=r;
nod[v].lc=nod[v].rc=false;
nod[v].nlen=nod[v].nseg=0;
nod[v].cnt=0;
if(r-l==1)
return;
buildtree(2*v,l,(l+r)/2);
buildtree(2*v+1,(l+r)/2,r);
}
void init(){
int i,xl,xr,yu,yd;
ycnt=0;
clr(sy);
for(i=0;i<n;i++){
scanf("%d%d%d%d",&xl,&yd,&xr,&yu);
e[2*i].yu=yu;
e[2*i].yd=yd;
e[2*i].x=xl;
e[2*i].tag=IN;
e[2*i+1].yu=yu;
e[2*i+1].yd=yd;
e[2*i+1].x=xr;
e[2*i+1].tag=OUT;
if(!sy[yd]){
yinterval[ycnt++]=yd;
sy[yd]=1;
}
if(!sy[yu]){
yinterval[ycnt++]=yu;
sy[yu]=1;
}
}
sort(yinterval,yinterval+ycnt);
for(i=0;i<ycnt;i++)
sy[yinterval[i]]=i;
sort(e,e+2*n,CP());
buildtree(1,0,ycnt-1);
}
void insert(int v,int l,int r){
if(l<=nod[v].l && nod[v].r<=r){
nod[v].nlen=yinterval[nod[v].r]-yinterval[nod[v].l];
nod[v].cnt++;
nod[v].nseg=1;
nod[v].lc=true;
nod[v].rc=true;
return;
}
if(l<nod[2*v].r)
insert(2*v,l,r);
if(r>nod[2*v+1].l)
insert(2*v+1,l,r);
if(nod[v].cnt==0){
nod[v].lc=nod[2*v].lc;
nod[v].rc=nod[2*v+1].rc;
nod[v].nlen=nod[2*v].nlen+nod[2*v+1].nlen;
nod[v].nseg=nod[2*v].nseg+nod[2*v+1].nseg;
if(nod[2*v].rc && nod[2*v+1].lc)
nod[v].nseg--;
}
}
void del(int v,int l,int r){
if(l<=nod[v].l && nod[v].r<=r){
nod[v].cnt--;
if(nod[v].cnt==0){
if(nod[v].r-nod[v].l==1){
nod[v].lc=nod[v].rc=false;
nod[v].nlen=nod[v].nseg=0;
}
else{
nod[v].lc=nod[2*v].lc;
nod[v].rc=nod[2*v+1].rc;
nod[v].nlen=nod[2*v].nlen+nod[2*v+1].nlen;
nod[v].nseg=nod[2*v].nseg+nod[2*v+1].nseg;
if(nod[2*v].rc && nod[2*v+1].lc)
nod[v].nseg--;
}
}
return;
}
if(l<nod[2*v].r)
del(2*v,l,r);
if(r>nod[2*v+1].l)
del(2*v+1,l,r);
if(nod[v].cnt==0){
nod[v].lc=nod[2*v].lc;
nod[v].rc=nod[2*v+1].rc;
nod[v].nlen=nod[2*v].nlen+nod[2*v+1].nlen;
nod[v].nseg=nod[2*v].nseg+nod[2*v+1].nseg;
if(nod[2*v].rc && nod[2*v+1].lc)
nod[v].nseg--;
}
}
void cal(){
yans=0;
xans=0;
int i;
insert(1,sy[e[0].yd],sy[e[0].yu]);
yans=nod[1].nlen;
memcpy(nod,nod+1,sizeof(nod[0]));
for(i=1;i<2*n;i++){
if(e[i].tag==IN)
insert(1,sy[e[i].yd],sy[e[i].yu]);
else
del(1,sy[e[i].yd],sy[e[i].yu]);
yans+=abs(nod[1].nlen-nod[0].nlen);
xans+=2*nod[0].nseg*(e[i].x-e[i-1].x);
memcpy(nod,nod+1,sizeof(nod[0]));
}
}
int main(){
while(scanf("%d",&n)!=EOF){
init();
cal();
printf("%d\n",yans+xans);
}
return 0;
}
#include <algorithm>
using namespace std;
#define IN 1
#define OUT 0
#define MAXN 10001
#define clr(x) memset(x,0,sizeof(x));
int n,ycnt,yinterval[2*MAXN],yans,xans;
//yinterval[i]=y表示纵坐标经过排序后第i个不同的纵坐标为y
int sy[2*MAXN];
//sy[y]=i表示纵坐标经过排序后y是第i小的纵坐标,与yinterval[i]=y互为反函数
struct Edge{
int yu,yd,x,tag;
}e[2*MAXN];
struct Node{
int l,r;
int cnt;
int nseg,nlen;
bool lc,rc;
}nod[3*MAXN];
class CP{
public:
int operator()(Edge &arg1,Edge &arg2){
return arg1.x<arg2.x;
}
};
void buildtree(int v,int l,int r){
nod[v].l=l;
nod[v].r=r;
nod[v].lc=nod[v].rc=false;
nod[v].nlen=nod[v].nseg=0;
nod[v].cnt=0;
if(r-l==1)
return;
buildtree(2*v,l,(l+r)/2);
buildtree(2*v+1,(l+r)/2,r);
}
void init(){
int i,xl,xr,yu,yd;
ycnt=0;
clr(sy);
for(i=0;i<n;i++){
scanf("%d%d%d%d",&xl,&yd,&xr,&yu);
e[2*i].yu=yu;
e[2*i].yd=yd;
e[2*i].x=xl;
e[2*i].tag=IN;
e[2*i+1].yu=yu;
e[2*i+1].yd=yd;
e[2*i+1].x=xr;
e[2*i+1].tag=OUT;
if(!sy[yd]){
yinterval[ycnt++]=yd;
sy[yd]=1;
}
if(!sy[yu]){
yinterval[ycnt++]=yu;
sy[yu]=1;
}
}
sort(yinterval,yinterval+ycnt);
for(i=0;i<ycnt;i++)
sy[yinterval[i]]=i;
sort(e,e+2*n,CP());
buildtree(1,0,ycnt-1);
}
void insert(int v,int l,int r){
if(l<=nod[v].l && nod[v].r<=r){
nod[v].nlen=yinterval[nod[v].r]-yinterval[nod[v].l];
nod[v].cnt++;
nod[v].nseg=1;
nod[v].lc=true;
nod[v].rc=true;
return;
}
if(l<nod[2*v].r)
insert(2*v,l,r);
if(r>nod[2*v+1].l)
insert(2*v+1,l,r);
if(nod[v].cnt==0){
nod[v].lc=nod[2*v].lc;
nod[v].rc=nod[2*v+1].rc;
nod[v].nlen=nod[2*v].nlen+nod[2*v+1].nlen;
nod[v].nseg=nod[2*v].nseg+nod[2*v+1].nseg;
if(nod[2*v].rc && nod[2*v+1].lc)
nod[v].nseg--;
}
}
void del(int v,int l,int r){
if(l<=nod[v].l && nod[v].r<=r){
nod[v].cnt--;
if(nod[v].cnt==0){
if(nod[v].r-nod[v].l==1){
nod[v].lc=nod[v].rc=false;
nod[v].nlen=nod[v].nseg=0;
}
else{
nod[v].lc=nod[2*v].lc;
nod[v].rc=nod[2*v+1].rc;
nod[v].nlen=nod[2*v].nlen+nod[2*v+1].nlen;
nod[v].nseg=nod[2*v].nseg+nod[2*v+1].nseg;
if(nod[2*v].rc && nod[2*v+1].lc)
nod[v].nseg--;
}
}
return;
}
if(l<nod[2*v].r)
del(2*v,l,r);
if(r>nod[2*v+1].l)
del(2*v+1,l,r);
if(nod[v].cnt==0){
nod[v].lc=nod[2*v].lc;
nod[v].rc=nod[2*v+1].rc;
nod[v].nlen=nod[2*v].nlen+nod[2*v+1].nlen;
nod[v].nseg=nod[2*v].nseg+nod[2*v+1].nseg;
if(nod[2*v].rc && nod[2*v+1].lc)
nod[v].nseg--;
}
}
void cal(){
yans=0;
xans=0;
int i;
insert(1,sy[e[0].yd],sy[e[0].yu]);
yans=nod[1].nlen;
memcpy(nod,nod+1,sizeof(nod[0]));
for(i=1;i<2*n;i++){
if(e[i].tag==IN)
insert(1,sy[e[i].yd],sy[e[i].yu]);
else
del(1,sy[e[i].yd],sy[e[i].yu]);
yans+=abs(nod[1].nlen-nod[0].nlen);
xans+=2*nod[0].nseg*(e[i].x-e[i-1].x);
memcpy(nod,nod+1,sizeof(nod[0]));
}
}
int main(){
while(scanf("%d",&n)!=EOF){
init();
cal();
printf("%d\n",yans+xans);
}
return 0;
}