hdu 1828 http://acm.hdu.edu.cn/showproblem.php?pid=1828
poj 1177 http://poj.org/problem?id=1177
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn= 5010;
struct node{
int lef, rig, mid, cov;
}seg[8*maxn];
struct point{
int lef, rig, pos, flag; //flag为1, 下边, flag为-1 上边
}px[2*maxn], py[2*maxn]; // px 为对y做线段树, py为对x做线段树
int disx[2*maxn], disy[2*maxn]; //离散坐标, 下标为离散值
int n, lenx, leny; //横纵坐标离散后长度
__int64 ans;
void init(){
int i, j, k, x1, y1, x2, y2;
for( i=0; i<n; i++){
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
px[i*2+1].lef= px[i*2].lef= y1;
px[i*2+1].rig= px[i*2].rig= y2;
px[i*2].pos= x1;
px[i*2].flag= 1;
px[i*2+1].pos= x2;
px[i*2+1].flag= -1;
py[i*2+1].lef= py[i*2].lef= x1;
py[i*2+1].rig= py[i*2].rig= x2;
py[i*2].pos= y1;
py[i*2].flag= 1;
py[i*2+1].pos= y2;
py[i*2+1].flag= -1;
disx[i*2]= x1;
disx[i*2+1]= x2;
disy[i*2]= y1;
disy[i*2+1]= y2;
}
}
bool cmp( point x, point y){
return x.pos < y.pos;
}
void disperse(){
sort( disx, disx+ 2*n);
sort( disy, disy+ 2*n);
lenx= unique(disx, disx+ 2*n)- disx;
leny= unique(disy, disy+ 2*n)- disy;
sort( px, px+ 2*n, cmp); //对y做线段树,按pos(即x)顺序由小及大排列
sort( py, py+ 2*n, cmp);
}
void maketree( int num, int lef, int rig){
seg[num].lef= lef;
seg[num].rig= rig;
seg[num].mid= (lef + rig) >> 1;
seg[num].cov= 0;
if( lef +1!= rig){
maketree( num*2, lef, seg[num].mid);
maketree( num*2+ 1, seg[num].mid, rig);
}
}
//1. 当seg[num].cov由0变1时,记录线段长度,并乘2,即上下对应两边长度和
//2. 对于seg[num].cov== 0且 左右点相符, 同时为新加线段,而非已有线段向下更新时,计起长度
//3. 若左右端点相符,且seg[num].cov>0时, seg[num].cov+= cov
//4. 若左右端点相符,seg[num].cov==0,并且为已有线段向下更新,而非新加入线段,seg[num].cov+= cov
//5. 对于某条seg[num].cov>0的线段,若要更新其一部分,即子线段,则先把这条线段的
// seg[num].cov更新到其所有子节点,再把seg[num].cov赋为-1, 再对其子线段进行更新
//6. tt 为1时,为新加线段,tt为0时,是已有线段向下更新
//7. tmp为1,对y建的线段树,tmp为0, 对x建的线段树
//8. 已经标记为-1的线段,不会再变为其他值
int insert( int num, int lef, int rig, int cov, int tt, int tmp){
if( seg[num].cov == 0 && seg[num].lef== lef && seg[num].rig== rig && tt== 1){
seg[num].cov= 1;
if( tmp== 1)return disy[rig]- disy[lef];
else return disx[rig]-disx[lef];
}
if( seg[num].cov >= 0 && seg[num].lef == lef && seg[num].rig== rig){
seg[num].cov+= cov;
return 0;
}
if( seg[num].cov > 0){
insert( num*2, seg[num].lef, seg[num].mid, seg[num].cov, 0, tmp);
insert( num*2+1, seg[num].mid, seg[num].rig, seg[num].cov, 0, tmp);
}
seg[num].cov= -1;
if( rig <= seg[num].mid)
return insert( num*2, lef, rig, cov, tt, tmp);
else if( lef >= seg[num].mid)
return insert( num*2+1, lef, rig, cov, tt, tmp);
else return insert( num*2, lef, seg[num].mid, cov, tt, tmp) + insert( num*2+1, seg[num].mid, rig, cov, tt, tmp);
}
int bx(int x){ //查找x的离散后坐标
int lef= 0, rig= lenx-1, mid;
while( lef <= rig){
mid= (lef + rig) >> 1;
if( disx[mid] < x) lef= mid+1;
else if( disx[mid] > x) rig= mid- 1;
else return mid;
}
}
int by(int y){
int lef= 0, rig= leny-1, mid;
while( lef <= rig){
mid= (lef + rig) >> 1;
if( disy[mid] < y) lef= mid+1;
else if( disy[mid] > y) rig= mid- 1;
else return mid;
}
}
int main(){
// freopen("1.txt", "r", stdin);
int i, aa;
while( scanf("%d", &n) != EOF){
init();
disperse();
ans= 0;
//分别对对x、y 扫描线, 求长度并
maketree(1, 0, leny);
for( i=0; i<2*n; i++){
ans+= insert(1, by(px[i].lef), by(px[i].rig), px[i].flag, 1, 1);
}
maketree(1, 0, lenx);
for( i=0; i<2*n; i++){
ans+= insert(1, bx(py[i].lef), bx(py[i].rig), py[i].flag, 1, 0);
}
printf("%d\n", ans*2);
}
return 0;
}