[离散化+扫描线+线段树]LightOJ 1120 - Rectangle Union

传送门:http://lightoj.com/volume_showproblem.php?problem=1120

1120 - Rectangle Union
Time Limit:2 second(s) Memory Limit:64 MB

Given some axis parallel rectangles, you have to find the union of their area. For example, see the shaded regions in the picture. Each rectangle will be denoted by four integers. They arex1, y1, x2, y2where(x1, y1)denotes the lower left corner and(x2, y2)denotes the upper right corner.

For the picture above, there are three rectangles. For the yellow rectangle the co-ordinates are (0, 2) and (3, 6). For the blue rectangle the co-ordinates are (1, 3) and (6, 7). For the green rectangle the co-ordinates are (2, 1) and (5, 4). So, the union area is (the shaded region) 31 square units.

Input

Input starts with an integerT (≤ 13), denoting the number of test cases.

Each case starts with a line containing an integern (1 ≤ n ≤ 30000). Each of the nextnlines will contain four integersx1, y1, x2, y2(0 ≤ x1, y1, x2, y2≤ 109, x1< x2, y1< y2)denoting a rectangle.

Output

For each case, print the case number and the union area.

Sample Input

Output for Sample Input

2

3

0 2 3 6

1 3 6 7

2 1 5 4

2

0 0 4 4

1 1 2 5

Case 1: 31

Case 2: 17

Notes

Dataset is huge, use faster I/O methods.

题意:很裸就矩形面积并,直接扫描线.

注意点:由于面积最大可以达到10^18次方,所以结果需要用long long,而且在中间计算时需要强制转换,否则会溢出.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 33333;
int x[MAXN<<1],t,n,sum[MAXN<<3],cnt[MAXN<<3],x_num,line_num;
unsigned __int64 ans;
struct Line{
    int l,r,h,s;
    Line(){}
    Line(int ll,int rr,int hh,int ss):l(ll),r(rr),h(hh),s(ss){}
    bool operator < (const Line &l) const{
        return h<l.h;
    }
}L[MAXN<<1];
#define lson l,m,rt<<1
#define rson m,r,rt<<1|1
void build(){
    memset(sum,0,sizeof(sum));
    memset(cnt,0,sizeof(cnt));
    x_num = line_num = 0;
    ans = 0;
}
void pushUP(int rt,int l,int r){
    if(cnt[rt]){
        sum[rt] = x[r]-x[l];
    }else{
        sum[rt] = sum[rt<<1]+sum[rt<<1|1];
    }
}
void update(int L,int R,int s,int l,int r,int rt){
    if(L<=l&&R>=r){
        cnt[rt]+=s;
        pushUP(rt,l,r);
        return;
    }
    if(l==r-1)return;
    int m = (l+r)>>1;
    if(m>L)update(L,R,s,lson);
    if(m<R)update(L,R,s,rson);
    pushUP(rt,l,r);
}
int search(int k){
    int l=0,r=x_num-1,m;
    while(l<=r){
        m = (l+r)>>1;
        if(x[m]==k)return m;
        else if(k<x[m])r = m-1;
        else l = m+1;
    }
    return -1;
}
int main(){
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++){
        scanf("%d",&n);
        build();
        for(int i=0;i<n;i++){
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            x[x_num++] = a;
            x[x_num++] = c;
            L[line_num++] = Line(a,c,b,1);
            L[line_num++] = Line(a,c,d,-1);
        }
        sort(x,x+x_num);sort(L,L+line_num);
        int temp = 1;
        for(int i=1;i<x_num;i++)if(x[i]!=x[i-1])x[temp++]=x[i];
        x_num = temp;
        for(int i=0;i<line_num;i++){
            int l = search(L[i].l);
            int r = search(L[i].r);
            if(!i){
                update(l,r,L[i].s,0,x_num-1,1);
            }else{
                ans += (__int64)sum[1]*(L[i].h-L[i-1].h);
                update(l,r,L[i].s,0,x_num-1,1);
            }
        }
        printf("Case %d: %llu\n",cas,ans);
    }
    return 0;
}



你可能感兴趣的:(UNION)