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

来源:互联网 发布:大学生单片机自学视频 编辑:程序博客网 时间:2024/05/21 09:35

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
210 10 20 2015 15 25 25.50
 

Sample Output
Test case #1Total 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 ;}

0 0
原创粉丝点击