摘要:矩形覆盖,求面积,线段树+离散+扫描
#include <stdio.h>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
const int size = 20000;
const int rectangle_num = 100;
typedef struct Vertical{
double x;
double up;
double low;
int flag;
}Vertical;
Vertical verticals[rectangle_num * 2];
vector<double> hash_map;
typedef struct Node{
int up;
int low;
int sc;
int uf;
int lf;
double cover_len;
int flag;
Node *left_child;
Node *right_child;
void Insert(int, int, int);
void Construct(int, int);
void Update();
}Node;
int len=1;
Node sTree[size * 3];
Node *root = &sTree[0];
void Node::Construct(int l, int u)
{
up = u;
low = l;
sc = 0;
uf = 0;
lf = 0;
cover_len = 0;
flag = 0;
if( low+1 == up){
left_child = right_child = NULL;
return;
}
int mid = ( up + low ) >> 1;
left_child = &sTree[len++];
right_child = &sTree[len++];
left_child->Construct(low, mid);
right_child->Construct(mid, up);
}
void Node::Insert(int l, int u, int f)
{
if( low>=l && up<=u ){
flag += f;
return;
}
int mid = ( low + up ) >> 1;
if( l < mid ){
left_child->Insert(l, u, f);
}
if( u > mid){
right_child->Insert(l, u, f);
}
}
void Node::Update()
{
if( flag > 0 ){
lf = 1;
uf = 1;
cover_len = hash_map[up] - hash_map[low];
sc = 1;
return;
}
if( low + 1 == up ){
lf = 0;
uf = 0;
cover_len = 0;
sc = 0;
return;
}
assert(left_child && right_child);
left_child->Update();
right_child->Update();
lf = left_child->lf;
uf = right_child->uf;
cover_len = left_child->cover_len + right_child->cover_len;
sc = left_child->sc + right_child->sc;
if( left_child->uf==1 && right_child->lf==1){
sc--;
}
}
bool compareVertical(Vertical one, Vertical two)
{
return one.x < two.x;
}
int findIndex(int left, int right, double value)
{
while( left <= right ){
int mid = (left + right) >> 1;
if(fabs(hash_map[mid] - value) < 0.000001){
return mid;
}
if( hash_map[mid] > value ){
right = mid - 1;
}else{
left = mid + 1;
}
}
}
int main()
{
int n;
int case_num = 1;
while(true){
scanf("%d", &n);
if( n == 0 ){
break;
}
int index = 0;
hash_map.clear();
for(int i=1; i<=n; i++){
float x1, y1, x2, y2;
scanf("%f%f%f%f", &x1, &y1, &x2, &y2);
Vertical elem;
elem.x= x1;
elem.low = y1;
elem.up = y2;
elem.flag = 1;
verticals[index++] = elem;
elem.x=x2;
elem.flag = -1;
verticals[index++] = elem;
hash_map.push_back(y1);
hash_map.push_back(y2);
}
sort(verticals, verticals+index, compareVertical);
sort(hash_map.begin(), hash_map.end());
vector<double>::iterator iter=unique(hash_map.begin(), hash_map.end());
hash_map.erase(iter, hash_map.end());
int hash_len = hash_map.size();
len = 1;
root->Construct(0, hash_len-1);
double previous_x = verticals[0].x;
double area = 0;
int last_sc = 0;
double last_len = 0;
root->Insert(findIndex(0, hash_len-1, verticals[0].low), findIndex(0, hash_len-1, verticals[0].up), verticals[0].flag);
for(int i=1; i<index; i++){
if(fabs(verticals[i].x-verticals[i-1].x) < 0.000001){
root->Insert(findIndex(0, hash_len-1, verticals[i].low), findIndex(0, hash_len-1, verticals[i].up), verticals[i].flag);
}else{
root->Update();
area += fabs(last_len * (verticals[i-1].x-previous_x));
//cout << previous_x << "/t" << area << endl;
last_sc = root->sc;
last_len = root->cover_len;
previous_x = verticals[i-1].x;
root->Insert(findIndex(0, hash_len-1, verticals[i].low), findIndex(0, hash_len-1, verticals[i].up), verticals[i].flag);
}
}
root->Update();
area += fabs(last_len * (verticals[index-1].x-previous_x));
printf("Test case #%d/n", case_num);
printf("Total explored area: %.2f/n/n", area);
case_num++;
}
return 0;
}