light oj 1120 扫描线

来源:互联网 发布:mac双系统win8.1镜像 编辑:程序博客网 时间:2024/06/01 09:51


Rectangle Union
Time Limit: 2000MSMemory Limit: 65536KB64bit IO Format: %lld & %llu

Submit Status uDebug

Description

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 are x1, y1, x2, y2 where (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 integer T (≤ 13), denoting the number of test cases.

Each case starts with a line containing an integer n (1 ≤ n ≤ 30000). Each of the next n lines will contain four integers x1, 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

2

3

0 2 3 6

1 3 6 7

2 1 5 4

2

0 0 4 4

1 1 2 5

Sample Output

Case 1: 31

Case 2: 17

Source

Problem Setter: Jane Alam Jan
Problem descriptions:
System Crawler 2016-08-08
Initialization.
Mo


模板


/*
1.保存矩形的上下边界,并且重要的,记录他们是属于上还是下,然后按高度升序排序
2.保存竖线坐标,并且去重,是为了离散化
3.以保存的上下边界数组去更新
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3
#define MAX 110
#define LCH(i) ((i)<<1)
#define RCH(i) ((i)<<1 | 1)


struct segment //保存矩形上下边界
{
  double l,r,h; //左右横坐标,纵坐标
  int f; //-1为下边界,1为上边界
}ss[2*MAX];
struct node //线段树节点
{
  int l,r;
  int cnt; //该节点被覆盖的情况
  double len; //该区间被覆盖的总长度
  int mid()
  { return (l+r)>>1; }
}tt[2*MAX*4];
double pos[2*MAX];
int nums;


int cmp(struct segment a ,struct segment b)
{
  return a.h<b.h;
}


void build(int a, int b ,int rt)
{
 tt[rt].l=a; tt[rt].r=b; tt[rt].cnt=0; tt[rt].len=0;
 if(a==b) return ;
 int mid=tt[rt].mid();
 build(a,mid,LCH(rt));
 build(mid+1,b,RCH(rt));
}


int binary(double key ,int low, int high)
{
   while(low<=high)
   {
      int mid=(low+high)>>1;
      if(pos[mid] == key) return mid;
      else if(key < pos[mid]) high=mid-1;
      else                    low=mid+1;
   }
   return -1;
}




void get_len(int rt)
{
   if(tt[rt].cnt) //非0,已经被整段覆盖
      tt[rt].len = pos[tt[rt].r+1] - pos[tt[rt].l];
   else if(tt[rt].l == tt[rt].r) //已经不是一条线段
      tt[rt].len = 0;
   else //是一条线段但是又没有整段覆盖,那么只能从左右孩子的信息中获取
      tt[rt].len = tt[LCH(rt)].len + tt[RCH(rt)].len ;
}


void updata(int a, int b ,int val ,int rt)
{
   if(tt[rt].l==a && tt[rt].r==b) //目标区间
   {
      tt[rt].cnt += val; //更新这个区间被覆盖的情况
      get_len(rt);  //更新这个区间被覆盖的总长度
      return ;
   }
   int mid=tt[rt].mid();
   if(b<=mid) //只访问左孩子
      updata(a,b,val,LCH(rt));
   else if(a>mid) //只访问有孩子
      updata(a,b,val,RCH(rt));
   else //左右都要访问
   {
      updata(a,mid,val,LCH(rt));
      updata(mid+1,b,val,RCH(rt));
   }
   get_len(rt); //计算该区间被覆盖的总长度
}


int main()
{
  int Case=0;
  int n;
  while(scanf("%d",&n)!=EOF && n)
  {
    nums=0;
    for(int i=0; i<n; i++)
    {
      double x1,y1,x2,y2;
      scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
      ss[nums].l=x1;  ss[nums].r=x2; ss[nums].h=y1; ss[nums].f=1;
      //记录上边界的信息
      ss[nums+1].l=x1; ss[nums+1].r=x2; ss[nums+1].h=y2; ss[nums+1].f=-1;
      //记录下边界的信息
      pos[nums]=x1; pos[nums+1]=x2;
      //记录横坐标
      nums += 2;


    }


    sort(ss,ss+nums,cmp); //横线按纵坐标升序排序
    sort(pos,pos+nums); //横坐标升序排序
    //for(int i=0; i<nums; i++) printf("%.2lf %.2lf  %.2lf\n",ss[i].l,ss[i].r,ss[i].h);
    int m=1;
    for(int i=1; i<nums; i++)
      if(pos[i]!=pos[i-1]) //去重
        pos[m++]=pos[i];


    build(0,m-1,1);  //离散化后的区间就是[0,m-1],以此建树
    double ans=0;
    for(int i=0; i<nums; i++) //拿出每条横线并且更新
    {
       int l=binary(ss[i].l,0,m-1);
       int r=binary(ss[i].r,0,m-1)-1;
       updata(l,r,ss[i].f,1); //用这条线段去更新
       ans += (ss[i+1].h-ss[i].h)*tt[1].len;
       //printf("%.2lf\n",ans);
    }
    printf("Test case #%d\n",++Case);
    printf("Total explored area: %.2f\n\n",ans);
  }
  return 0;
}




#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int N = 300100;
struct node1
{
    int l, r, h, cnt;
}p[N<<2];
struct node2
{
    int l, r, h, cnt;
    long long len;
}tree[N<<2];
int x[N<<2];
int cmp(node1 a,node1 b)
{
    return a.h<b.h;
}
void build(int l,int r,int rt);
int binary(int z,int a,int b);
void update(int L,int R,int k,int l,int r,int rt);
void pushup(int rt);


int main()
{
    int t, ncase=1;
    scanf("%d", &t);
    while(t--)
    {
        int n;
        scanf("%d", &n);
        int k=0;
        for(int i=0;i<n;i++)
        {
            int x1, y1, x2, y2;
            scanf("%d %d %d %d",&x1, &y1, &x2, &y2);
            p[k].l=x1,p[k].r=x2,p[k].h=y1, p[k].cnt=1;
            p[k+1].l=x1,p[k+1].r=x2,p[k+1].h=y2, p[k+1].cnt=-1;
            x[k]=x1, x[k+1]=x2;
            k+=2;
        }
        sort(p,p+k,cmp);
        sort(x,x+k);
        int m=1;
        for(int i=1;i<k;i++)
        {
            if(x[i]!=x[i-1])
            {
                x[m++]=x[i];
            }
        }
        build(0,m-1,1);
        long long sum=0;
        for(int i=0;i<k-1;i++)
        {
            int l=binary(p[i].l,0,m-1);
            int r=binary(p[i].r,0,m-1)-1;
            update(l,r,p[i].cnt,0,m-1,1);
            sum+=(p[i+1].h-p[i].h)*tree[1].len;
        }
        printf("Case %d: %lld\n",ncase++,sum);
    }
    return 0;
}


void build(int l,int r,int rt)
{
    tree[rt].l=l,tree[rt].r=r,tree[rt].len=0,tree[rt].cnt=0;
    if(l==r)
    {
        return ;
    }
    int mid=(l+r)/2;
    build(lson);
    build(rson);
    return ;
}


int binary(int z,int a,int b)
{
    int l=a, r=b, mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(x[mid]==z)
        {
            return mid;
        }
        else if(x[mid]<z)
        {
            l=mid+1;
        }
        else
        {
            r=mid-1;
        }
    }
    return -1;
}


void update(int L,int R,int k,int l,int r,int rt)
{
    if(tree[rt].l==L&&tree[rt].r==R)
    {
        tree[rt].cnt+=k;
        pushup(rt);
        return ;
    }
    int mid=(l+r)/2;
    if(R<=mid)
    {
        update(L,R,k,lson);
    }
    else if(L>mid)
    {
        update(L,R,k,rson);
    }
    else
    {
        update(L,mid,k,lson);
        update(mid+1,R,k,rson);
    }
    pushup(rt);
}


void pushup(int rt)
{
    if(tree[rt].cnt!=0)
    {
        tree[rt].len=x[tree[rt].r+1]-x[tree[rt].l];
    }
    else if(tree[rt].l==tree[rt].r)
    {
        tree[rt].len=0;
    }
    else
    {
        tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len;
    }
    return ;
}

0 0