我是靠谱客的博主 开放电源,最近开发中收集的这篇文章主要介绍杭电 HDU ACM 1225 Atlantis (线段树 扫描线 离散化 最基本)acm第一发扫描线问题,其实算法原理很好理解 ,但是具体实现起来还是遇到诸多问题,我尝试参考了网上两份对于解决 线段树表示区间问题的方法, 第一种是每个结点的真实值,比如对于更新离散化后的1 ~ 4区间,我们在线段树中更新的是1 ~ 3,这样单个结点也可以表示一个最小单位区间。 第二种那就是在建树的时候改变通常策略,1 ~ 10 为总区间,两个孩子为1 ~ 5 ,5 ~ 10。 核心难点:当我们每次找到需要更新的,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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 #%dnTotal explored area: %.2lfnn",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 #%dnTotal explored area: %.2lfnn",cs++ , ans);
}
return 0 ;
}

最后

以上就是开放电源为你收集整理的杭电 HDU ACM 1225 Atlantis (线段树 扫描线 离散化 最基本)acm第一发扫描线问题,其实算法原理很好理解 ,但是具体实现起来还是遇到诸多问题,我尝试参考了网上两份对于解决 线段树表示区间问题的方法, 第一种是每个结点的真实值,比如对于更新离散化后的1 ~ 4区间,我们在线段树中更新的是1 ~ 3,这样单个结点也可以表示一个最小单位区间。 第二种那就是在建树的时候改变通常策略,1 ~ 10 为总区间,两个孩子为1 ~ 5 ,5 ~ 10。 核心难点:当我们每次找到需要更新的的全部内容,希望文章能够帮你解决杭电 HDU ACM 1225 Atlantis (线段树 扫描线 离散化 最基本)acm第一发扫描线问题,其实算法原理很好理解 ,但是具体实现起来还是遇到诸多问题,我尝试参考了网上两份对于解决 线段树表示区间问题的方法, 第一种是每个结点的真实值,比如对于更新离散化后的1 ~ 4区间,我们在线段树中更新的是1 ~ 3,这样单个结点也可以表示一个最小单位区间。 第二种那就是在建树的时候改变通常策略,1 ~ 10 为总区间,两个孩子为1 ~ 5 ,5 ~ 10。 核心难点:当我们每次找到需要更新的所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部