您的位置:首页 > 其它

杭电 HDU ACM 1225 Atlantis (线段树 扫描线 离散化 最基本)

2015-08-11 12:51 465 查看

acm第一发扫描线问题,其实算法原理很好理解 ,但是具体实现起来还是遇到诸多问题,我尝试参考了网上两份对于解决 线段树表示区间问题的方法, 第一种是每个结点的真实值,比如对于更新离散化后的1 ~ 4区间,我们在线段树中更新的是1 ~ 3,这样单个结点也可以表示一个最小单位区间。 第二种那就是在建树的时候改变通常策略,1 ~ 10 为总区间,两个孩子为1 ~ 5 ,5 ~
10。

核心难点:当我们每次找到需要更新的区间,首先应该更新cover值,然后判断此时是被覆盖了,还是解除覆盖了,如果刚好被覆盖,那么此结点的sum值也就为结点真实区间值。如果是刚好解除覆盖,那么需要看看是否有他的孩子是被覆盖的,如果有,那么应该把两孩子值加到父亲sum上。

回溯时要判断每个子树根节点是否被覆盖,如果被覆盖那么就用当前父节点的值继续参与往上递归,如果未覆盖父节点就应该把孩子值更新上来,然后继续参与往上递归。 就会发现如果从根节点往下看,能够看到的第一层被覆盖的结点所表示的区间组合起来恰好就是总区间的sum值。

Atlantis

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 8948 Accepted Submission(s): 3833



Problem 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 file 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




Source
Mid-Central European Regional Contest 2000

version 1:

/*=============================================================================
#
#      Author: liangshu - cbam 
#
#      QQ : 756029571 
#
#      School : 哈尔滨理工大学 
#
#      Last modified: 2015-08-11 12:30
#
#     Filename: A.cpp
#
#     Description: 
#        The people who are crazy enough to think they can change the world, are the ones who do ! 
=============================================================================*/
#

#include<iostream>    
#include<sstream>    
#include<algorithm>    
#include<cstdio>    
#include<string.h>    
#include<cctype>    
#include<string>    
#include<cmath>    
#include<vector>    
#include<stack>    
#include<queue>    
#include<map>    
#include<set>    
using namespace std;

const int INF = 2024;
struct line {
    double s, e, y, mark;
    line(double s, double e, double y, double ma):s(s),e(e),y(y), mark(ma){}
    bool friend operator < (line a, line  b){
        return a.y < b.y;
    }
};

struct Tree{
    int cover;
    int lft,rht;double sum;
}tree[INF<<2];

vector<double>X;
vector<line>L;
map<double, int>h;

void create(int root, int left, int right){
    tree[root].lft = left;
    tree[root].rht = right;
    tree[root].sum = 0;
    if(left + 1 != right){
        int mid = (left + right)/2;
        create(root<<1, left, mid);
        create(root<<1|1, mid, right);
    }
    return ;
}

void update(int root, int val, int left, int right){
    if(tree[root].lft >= left && tree[root].rht <= right){
        tree[root].cover += val;
        if(tree[root].cover){
            tree[root].sum =  X[tree[root].rht] - X[tree[root].lft];return ;
        }
        else{
            tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;
            return ;
        }
    }
    if(tree[root].lft == tree[root].rht)return ;
    int mid = (tree[root].lft + tree[root].rht)/2;
    if(left < mid){
        update(root <<1, val, left, right);
    }
    if(right >= mid){
        update(root<<1|1,val,left, right);
    }
    if(!tree[root].cover)
    tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;
}

int main(){
    int n,cs = 1;
    while(~scanf("%d", &n)&&n){
        h.clear();L.clear();X.clear();
        double x1, y1, x2, y2;
        for(int i = 1; i <= n; i++){
            scanf("%lf%lf%lf%lf",&x1, &y1, &x2, &y2);
            L.push_back(line(x1, x2, y1, 1));
            L.push_back(line(x1, x2, y2, -1));
            X.push_back(x1);X.push_back(x2);
        }
        sort(X.begin(), X.end());
        sort(L.begin(), L.end());
       X.erase(unique(X.begin(),X.end()), X.end());
       for(int i = 0; i < X.size(); i++){
           h[X[i]] = i;
       }
       create(1, 0, X.size() - 1);
       double ans = 0;int i;
       for( i = 0; i < L.size() - 1; i++){
           update(1, L[i].mark, h[L[i].s], h[L[i].e]);
               ans += (L[i + 1].y - L[i].y) * tree[1].sum;
       }
           update(1, L[i].mark, h[L[i].s], h[L[i].e]);
       printf("Test case #%d\nTotal explored area: %.2lf\n\n",cs++ , ans);
    }
}


version 2 :

/*=============================================================================
#
#      Author: liangshu - cbam 
#
#      QQ : 756029571 
#
#      School : 哈尔滨理工大学 
#
#      Last modified: 2015-08-11 12:50
#
#     Filename: A.cpp
#
#     Description: 
#        The people who are crazy enough to think they can change the world, are the ones who do ! 
=============================================================================*/
#

#include<iostream>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<cctype>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
using namespace std;
const int INF = 2222;

struct line
{
    double s, e, y, mark;
} L[INF];

double sum[INF<<2];
int cnt[INF<<2];
vector<double>dict;

bool cmp(line a, line b)
{
    return a.y < b.y;
}

void pushup(int rt, int l, int r)
{
    if(cnt[rt])
    {
        sum [rt] = dict[r + 1] - dict[l] ;
    }
    else
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
int  bin(double k, int len)
{
    int l = 0, r = len - 1;
    while (l <= r)
    {
        int mid = (l + r)>>1;
        if(dict[mid] == k)return mid;
        else if(dict[mid] > k)r = mid - 1;
        else l = mid + 1;
    }
    return -1;
}
void  update(int rt, int L, int R, int l ,int r, int val)
{
    if(L <= l && r <= R)
    {
        cnt[rt] += val;
        pushup(rt, l, r);
        return ;
    }
    int mid = (l + r)>>1;
    if(L <= mid)update(rt<<1, L, R, l , mid, val);
    if(R > mid)update(rt<<1|1,L, R, mid + 1, r, val);
    pushup(rt,l, r);
}

int main()
{
    int n,cs = 1;
    while(scanf("%d", &n) != EOF && n)
    {
        memset(sum, 0, sizeof(sum));
        int t = 0;
        for(int i = 1; i <= n; i++)
        {
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            dict.push_back (x1);
            L[t].s = x1;
            L[t].e = x2;
            L[t].y = y1;
            L[t++].mark = 1;
            dict.push_back(x2);
            L[t].s = x1;
            L[t].e = x2;
            L[t].y = y2;
            L[t++].mark = -1 ;
        }
        sort(L , L + t, cmp);
        sort(dict .begin(), dict.end());
        dict.erase (unique(dict.begin(), dict.end()), dict.end());
        double ans = 0;
        for(int i = 0; i < t ; i ++ )
        {
            int l = bin(L[i].s, dict.size());
            int r = bin(L[i].e, dict.size()) - 1;
            if(l <= r)
                update(1, l, r, 0, dict.size() - 1, L[i].mark);
            ans += sum[1] * (L[i + 1].y - L[i].y);
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n\n",cs++ , ans);
    }
    return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: