來源:http://poj.org/problem?id=1177
題意:給出一些矩形,求出這些矩形所圍城的周長。
思路:明顯是線段樹的題目啊,但是線段樹爛的一扯。。。具體來說,就是一條線段一條線段的來處理。先處理豎着的線段,再處理橫着的線段。處理線段長度的時候和掃描線求面積是一樣的。
代碼:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
const int N = 5010,M = 20010;
struct line
{
int lp,rp,value,flag;
}seg1[N * 2],seg2[N * 2];
struct tree
{
int lp,rp,len,cnt;
int getmid()
{
return (lp + rp) / 2;
}
}tt[M * 8];
bool cmp(line a ,line b)
{
if(a.value == b.value)
{
return a.flag > b.flag;
}
return a.value < b.value;
}
void built_tree(int lp,int rp,int pos)
{
tt[pos].lp = lp, tt[pos].rp = rp;
tt[pos].len = 0, tt[pos].cnt = 0;
if(lp == rp)
{
return;
}
int mid = tt[pos].getmid();
built_tree(lp,mid,pos * 2);
built_tree(mid+1,rp,pos * 2 + 1);
}
void update(int lp,int rp,int add,int pos)
{
if(tt[pos].lp == lp && tt[pos].rp == rp)
{
tt[pos].cnt += add;
if(tt[pos].cnt)
{
tt[pos].len = rp - lp + 1;
}
else
{
tt[pos].len = tt[pos * 2].len + tt[pos * 2 + 1].len;
}
return;
}
int mid = tt[pos].getmid();
if(rp <= mid)
{
update(lp,rp,add,pos * 2);
}
else if(lp > mid)
{
update(lp,rp,add,pos * 2 + 1);
}
else
{
update(lp,mid,add,pos * 2);
update(mid+1,rp,add,pos * 2 + 1);
}
if(tt[pos].cnt)
{
tt[pos].len = tt[pos].rp - tt[pos].lp + 1;
}
else
{
tt[pos].len = tt[pos * 2].len + tt[pos * 2 + 1].len;
}
}
int fun(int x)
{
if(x < 0)
{
return -x;
}
return x;
}
int main()
{
//freopen("1.txt","r",stdin);
//freopen("2.txt","w",stdout);
int n;
while(scanf("%d",&n) != EOF)
{
int x1,y1,x2,y2;
for(int i = 0; i < n; ++i)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1 += 10001, y1 += 10001, x2 += 10001, y2 += 10001;
seg1[i].lp = x1, seg1[i].rp = x2 - 1 , seg1[i].value = y1, seg1[i].flag = 1;
seg1[i + n].lp = x1, seg1[i + n].rp = x2 - 1 , seg1[i + n].value = y2, seg1[i + n].flag = -1;
seg2[i].lp = y1, seg2[i].rp = y2 - 1, seg2[i].value = x1, seg2[i].flag = 1;
seg2[i + n].lp = y1, seg2[i + n].rp = y2 - 1, seg2[i + n].value = x2, seg2[i + n].flag = -1;
}
sort(seg1,seg1 + n * 2,cmp);
sort(seg2,seg2 + n * 2,cmp);
built_tree(1, M, 1);
int ans = 0;
for(int i = 0,j = 0; i < 2 * n ; ++i)
{
update(seg1[i].lp,seg1[i].rp,seg1[i].flag,1);
ans += fun(tt[1].len - j);
j = tt[1].len;
}
for(int i = 0; i < M * 4; ++i)
{
tt[i].cnt = 0, tt[i].len = 0;
}
for(int i = 0,j = 0; i < 2 * n ; ++i)
{
update(seg2[i].lp,seg2[i].rp,seg2[i].flag,1);
ans += fun(tt[1].len - j);
j = tt[1].len;
}
printf("%d\n",ans);
}
return 0;
}