题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828
题意:给出一些矩形,求并后的周长。
哈希后,扫描即可。第一道扫描线的题目,尽管是裸题,还是可开心~~
参考代码:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
#define clr(arr,val) memset(arr,val,sizeof(arr))
const int M = 5005;
enum In{lt,rt};
int n;
int hash_y[M*4],num_y[M*2],decod[M*2],MaxY;
struct rectangle{
int x1,y1,x2,y2;
}rec[M];
struct SegTree{
int count;
int depth,amount,L,R,lv,rv;
}Tree[M*4];
void Update(int,int,int);
void Build(int root,int L,int R){
Tree[root].amount = 0;
Tree[root].lv = Tree[root].rv = 0;
Tree[root].count = Tree[root].depth = 0;
Tree[root].L = L;
Tree[root].R = R;
if(L == R - 1) return ;
Build(root<<1,L,(L+R)/2);
Build((root<<1)+1,(L+R)/2,R);
}
void Insert(int root,int L,int R){
if(Tree[root].L >= hash_y[L] && Tree[root].R <= hash_y[R]){
Tree[root].count++;
Update(root,L,R);
}
else {
if(hash_y[L] < (Tree[root].L+Tree[root].R)/2){
Insert(root<<1,L,R);
Update(root,L,R);
}
if(hash_y[R] > (Tree[root].L+Tree[root].R)/2){
Insert((root<<1)+1,L,R);
Update(root,L,R);
}
}
}
void Delete(int root,int L,int R){
if(Tree[root].L >= hash_y[L] && Tree[root].R <= hash_y[R]){
Tree[root].count--;
Update(root,L,R);
}
else {
if(hash_y[L] < (Tree[root].L+Tree[root].R)/2){
Delete(root<<1,L,R);
Update(root,L,R);
}
if(hash_y[R] > (Tree[root].L+Tree[root].R)/2){
Delete((root<<1)+1,L,R);
Update(root,L,R);
}
}
}
void Update(int root,int L,int R){
if(Tree[root].count > 0){
Tree[root].depth = decod[Tree[root].R] - decod[Tree[root].L];
Tree[root].amount = 1;
Tree[root].lv = 1;
Tree[root].rv = 1;
Tree[root].amount = 1;
return ;
}
if(Tree[root].L == Tree[root].R - 1) {
if(Tree[root].count == 0){
Tree[root].depth = 0;
Tree[root].amount = 0;
Tree[root].lv = 0;
Tree[root].rv = 0;
}
return ;
}
if(Tree[root].count == 0){
Tree[root].rv = Tree[(root<<1)+1].rv;
Tree[root].lv = Tree[root<<1].lv;
Tree[root].depth = Tree[root<<1].depth + Tree[(root<<1)+1].depth;
Tree[root].amount = Tree[root<<1].amount + Tree[(root<<1)+1].amount
- Tree[root<<1].rv * Tree[(root<<1)+1].lv;
}
}
struct operation{
In in;
int x,lower_y,high_y;
}Event[M*4];
void input(){
for(int i = 0;i < n;++i){
cin>>rec[i].x1>>rec[i].y1>>rec[i].x2>>rec[i].y2;
rec[i].x1 += M * 2;
rec[i].x2 += M * 2;
rec[i].y1 += M * 2;
rec[i].y2 += M * 2;
}
}
void Hash(){
clr(hash_y,-1);
for(int i = 0;i < n;++i){
num_y[i*2] = rec[i].y1;
num_y[i*2+1] = rec[i].y2;
Event[i*2].in = lt;
Event[i*2].x = rec[i].x1;
Event[i*2].lower_y = rec[i].y1;
Event[i*2].high_y = rec[i].y2;
Event[i*2+1].in = rt;
Event[i*2+1].x = rec[i].x2;
Event[i*2+1].lower_y = rec[i].y1;
Event[i*2+1].high_y = rec[i].y2;
}
sort(num_y,num_y+n*2);
MaxY = 0;
for(int i = 0;i < n*2;++i){
if(hash_y[ num_y[i] ] == -1){
hash_y[ num_y[i] ] = ++ MaxY;
decod[MaxY] = num_y[i];
}
}
}
bool cmp(operation a,operation b){ return a.x < b.x; }
void solve(){
input();
Hash();
Build(1,1,MaxY);
sort(Event,Event+n*2,cmp);
int ans = 0;
int last_amount = 0,now_amount,last_depth = 0,now_depth = 0;
for(int i = 0;i < n*2;++i){
if(Event[i].in == lt)
Insert(1,Event[i].lower_y,Event[i].high_y);
else
Delete(1,Event[i].lower_y,Event[i].high_y);
now_amount = Tree[1].amount;
now_depth = Tree[1].depth;
ans += last_amount * 2 * (i?(Event[i].x-Event[i-1].x):0);
ans += abs(now_depth - last_depth);
last_amount = now_amount;
last_depth = now_depth;
}
cout<<ans<<endl;
}
int main(){
while(cin>>n){
solve();
}
return 0;
}