POJ1177 Picture

题意

Language:
Picture
Time Limit: 2000MS Memory Limit: 10000K
Total Submissions: 14427 Accepted: 7542

Description

A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the union of all rectangles is called the perimeter.

Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.

The corresponding boundary is the whole set of line segments drawn in Figure 2.

The vertices of all rectangles have integer coordinates.

Input

Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate.

0 <= number of rectangles < 5000
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

Output

Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.

Sample Input

7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16

Sample Output

228

Source

给出多个矩形坐标,求所有矩形的组合体的周长

分析

参照A_Mango的题解。

这道题的突破口是线扫描,假想一条垂直于y轴的线从下往上扫描,以矩形x轴方向的边为事件,这样只要知道当前发生事件时矩形的覆盖x轴的长度(为了计算x轴方向的边),以及由几块孤立的区域组成(为了计算y轴方向的边),但是问题就是如何在每次更新事件时更新这两个属性

这就到了线段树出场,因为如果要维护这2个属性,必须要在矩形下边的边时加入它,在上边时把它删除,能快速做到对一个线段快速修改就是线段树了,而且对于维护一个区域内的线段的总长度,以及孤立的线段数量,它也不难实现,但这时候问题来了,坐标的范围是-10000~10000,正常用这个坐标来更新线段树的话速度可能不够。所以最好的办法就是先对矩形边的x坐标离散化(不过本题中如果数据不太变态,不离散化估计也能过)

线段树的维护:这也是一个难点,越用这东西越觉得它有很多东西值得钻研。本题中要维护的2个线段树属性

  1. 覆盖的总线段长
    因为对同个区域插入多次,他的总长度还是不变,对一个区域删除的次数要等于他插入的次数才能把区域中的长度减少,所以要在每个节点加上覆盖次数cover
  2. 孤立线段的数量
    因为要判断2个子区域是否相连,加上bl,br记录当前节点左右边界是否被覆盖

时间复杂度\(O(n \log n)\)

代码

#include<iostream>
#include<algorithm>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;rg char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
    while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std;

co int N=2e4+1,INF=0x3f3f3f3f;
int n,Max=-INF,Min=INF,tot,ans,pre;
struct P{
    int l,r,h,k;
    il bool operator<(co P&p)co {return h!=p.h?h<p.h:k>p.k;}
}a[N];
struct T{
    int sum,num,len;
    bool l,r;
}t[N*4];
il void add(int l,int r,int h,int k){
    a[++tot].l=l,a[tot].r=r,a[tot].h=h,a[tot].k=k;
}
#define lc (p<<1)
#define rc (p<<1|1)
il void work(int p,int l,int r){
    if(t[p].sum) t[p].num=t[p].l=t[p].r=1,t[p].len=r-l+1;
    else if(l==r) t[p].len=t[p].num=t[p].l=t[p].r=0;
    else{
        t[p].len=t[lc].len+t[rc].len;
        t[p].num=t[lc].num+t[rc].num;
        if(t[lc].r&&t[rc].l) --t[p].num;
        t[p].l=t[lc].l,t[p].r=t[rc].r;
    }
}
void change(int p,int l,int r,int L,int R,int k){
    if(L<=l&&r<=R) return t[p].sum+=k,work(p,l,r);
    int mid=l+r>>1;
    if(L<=mid) change(lc,l,mid,L,R,k);
    if(R>mid) change(rc,mid+1,r,L,R,k);
    work(p,l,r);
}
int main(){
//  freopen(".in","r",stdin),freopen(".out","w",stdout);
    read(n);
    for(int i=1,x1,y1,x2,y2;i<=n;++i){
        read(x1),read(y1),read(x2),read(y2);
        Max=max(Max,max(x1,x2)),Min=min(Min,min(x1,x2));
        add(x1,x2,y1,1),add(x1,x2,y2,-1);
    }
    if(Min<=0){
        for(int i=1;i<=tot;++i) a[i].l+=1-Min,a[i].r+=1-Min;
        Max-=Min; // len-1
    }
    sort(a+1,a+tot+1);
    for(int i=1;i<=tot;++i){
        change(1,1,Max,a[i].l,a[i].r-1,a[i].k);
        while(a[i].h==a[i+1].h&&a[i].k==a[i+1].k)
            ++i,change(1,1,Max,a[i].l,a[i].r-1,a[i].k);
        ans+=abs(t[1].len-pre),pre=t[1].len;
        ans+=t[1].num*(a[i+1].h-a[i].h)*2;
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/autoint/p/10660913.html
今日推荐