zoukankan      html  css  js  c++  java
  • 线段树---Atlantis

    题目网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110064#problem/A

    Description

    There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

    Input

    The input consists of several test cases. Each test case starts with a line containing a single integer n (1 <= n <= 100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.
    The input file is terminated by a line containing a single 0. Don't process it.

    Output

    For each test case, your program should output one section. The first line of each section must be "Test case #k", where k is the number of the test case (starting with 1). The second one must be "Total explored area: a", where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point. 
    Output a blank line after each test case.

    Sample Input

    2
    10 10 20 20
    15 15 25 25.5
    0

    Sample Output

    Test case #1
    Total explored area: 180.00 

    题意: 给了n个矩形的左下角和右上角的坐标,求矩形面积的并(矩形可能覆盖在一起,求总面积);

    思路:使用线段树记录所有矩形上下两条边的高度,用结构体数组记录矩形的左右两条边,并按照从左往右的顺序排序,从左到右加上每一个小矩形的面积。


    代码如下:
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #define N 210
    using namespace std;
    double y[N];
    
    struct node
    {
        double x,y1,y2;
        int f;
    }Line[N];
    
    struct node1
    {
        double lf,rf,cnt;
        int l,r,c;
    }tree[N*3];
    
    int cmp1(const node a,const node b)
    {
        return a.x < b.x;
    }
    
    int cmp2(const void *a,const void *b)
    {
        return *(double *)a>*(double *)b?1:-1;
    }
    
    void bulid(int t,int l,int r)
    {
        int mid;
        tree[t].c=0; tree[t].cnt=0;
        tree[t].l=l;
        tree[t].r=r;///记录着所有矩形的两条竖边从左到右的顺序编号;
        tree[t].lf=y[l];
        tree[t].rf=y[r];
        if(l+1==r) return;
        mid=(l+r)/2;
        bulid(2*t,l,mid);
        bulid(2*t+1,mid,r);
    }
    
    void calen(int t)
    {
        if(tree[t].c>0)
        {
            tree[t].cnt=tree[t].rf-tree[t].lf;
            return ;
        }
        if(tree[t].l+1==tree[t].r) tree[t].cnt=0;///是矩形右面的边则将树节点的值清零;
        else tree[t].cnt=tree[2*t].cnt+tree[2*t+1].cnt;///计算父节点的值;
    }
    
    void updata(int t,node e)
    {
        if(e.y1 == tree[t].lf && e.y2==tree[t].rf)
        {
            tree[t].c+=e.f;
            calen(t);
            return;
        }
        if(e.y2 <=tree[2*t].rf ) updata(2*t,e);
        else if(e.y1 >=tree[2*t+1].lf) updata(2*t+1,e);
        else
        {
            node tmp=e;
            tmp.y2=tree[2*t].rf;
            updata(2*t,tmp);
            tmp=e;
            tmp.y1=tree[2*t+1].lf;
            updata(2*t+1,tmp);
        }
        calen(t);///计算各个父节点的cnt值;
    }
    
    int main()
    {
        int Case=0,n,t;
        double x1,y1,x2,y2,ans;
        while(scanf("%d",&n)!=EOF && n)
        {
            Case++;
            t=1;
            for(int i=1;i<=n;i++)
            {
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                Line[t].x=x1;
                Line[t].y1=y1;
                Line[t].y2=y2;
                Line[t].f=1;
                y[t]=y1;
    
                Line[t+1].x=x2;
                Line[t+1].y1=y1;
                Line[t+1].y2=y2;
                Line[t+1].f=-1;
                y[t+1]=y2;
                t+=2;
            }
            sort(Line+1,Line+t-1,cmp1);///对结构体Line按x值从小到大进行排序;
            qsort(y+1,t-1,sizeof(y[1]),cmp2);///对y[]数组进行从小到大的排序;
            bulid(1,1,t-1);
            ans=0;
            for(int i=1;i<t;i++)
            {
                ans+=tree[1].cnt*(Line[i].x - Line[i-1].x);
                updata(1,Line[i]);
            }
            printf("Test case #%d
    Total explored area: %.2lf
    
    ",Case,ans);
        }
        return 0;
    }
  • 相关阅读:
    Flash中先获取flv的尺寸然后再显示的方法
    雕虫小艺:Slider控件的制作(Flash)
    用几十行代码写一个可以在PC Web,PC桌面,安卓,iOS上运行的程序
    仰望星空,结果南辕北辙
    Flash播放mp4的两个问题:编码问题和需要下载完后才能播放的问题
    只学一点点:我的技术学习策略
    2012年计划
    提高ipad浏览器下大尺寸xml文件解析的性能
    html5/haXe开发偶感
    支点:技术选择的精髓
  • 原文地址:https://www.cnblogs.com/chen9510/p/5324264.html
Copyright © 2011-2022 走看看