题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828
具体看 http://www.cnblogs.com/shuaiwhu/archive/2012/04/22/2464876.html 的讲解
我一开始连讲解都听不懂 直接看代码才慢慢明白的
看了一遍他的代码 自己手打了一遍 所以几乎一样~
#include#include <string.h> #include #define MAX 5010 #define ABS(X) ((X)>=0?(X):(-(X))) using namespace std; struct node { int x, y1, y2, flag; }scan[MAX<<1]; int y[MAX<<1]; struct Tree { int l, r, cnt, line, lbd, rbd, sum; }tree[MAX<<4]; int cmp1( const void *a, const void *b ) { node *c = (node *)a ; node *d = (node *)b ; if( c->x == d->x ) return c->flag <= d->flag ?1:-1; //先处理输入再处理输出,两条竖线重叠时才不计算ans内
else return c->x >= d->x ?1:-1; } int cmp2( const void *a, const void *b ) { return *(int *)a >= *(int *)b ?1: -1; } void build( int l, int r, int pos ) { tree[pos].l = l, tree[pos].r = r; tree[pos].cnt = tree[pos].line = tree[pos].lbd = tree[pos].rbd =tree[pos].sum = 0; if( l + 1 == r ) //叶节点不需要再分 再中分就再跳不出去
return ; else { int mid = (tree[pos].l + tree[pos].r)/2 ; build( l, mid, pos*2 ); build(mid, r, pos*2+1 ); } } void update_sum( int pos ) { if(tree[pos].cnt > 0) tree[pos].sum = y[tree[pos].r] - y[tree[pos].l]; // else if( tree[pos].l == tree[pos].r ) // return ; else { tree[pos].sum = tree[pos*2].sum + tree[pos*2+1].sum ; } } void update_line( int pos ) { if( tree[pos].cnt > 0 ) { tree[pos].lbd = tree[pos].rbd = 1; tree[pos].line = 1; } else { tree[pos].lbd = tree[pos*2].lbd; tree[pos].rbd = tree[pos*2+1].rbd; //注意两个子节点连续的情况,即tree[pos*2].rbd=tree[pos*2+1].lbd=1
tree[pos].line = tree[pos*2].line + tree[pos*2+1].line - rbd*tree[pos*2+1].lbd ;
} } void update( int l, int r, int pos, int mark ) { int mid = (tree[pos].l + tree[pos].r)/2 ; if( y[tree[pos].l] == l && y[tree[pos].r] == r ) //y储存的是真正的纵坐标, tree[pos].l,tree[pos].r储存的只是映射的
mark == 1 ?tree[pos].cnt ++ : tree[pos].cnt --; else if( tree[pos].l + 1 == tree[pos].r ) //是叶节点且不是匹配的l r直接返回 不update_sum,update_line。 注意这里else if 的意思 是前面两个条件缺一不可
return ; else if( r <= y[mid] ) update(l, r, pos*2, mark); else if( l >= y[mid] ) update(l, r, pos*2+1,mark); else { update(l, y[mid], pos*2, mark); update(y[mid], r, pos*2+1, mark); } update_sum( pos ); update_line( pos ); } int main() { int i, x1, y1, x2, y2, n, ans; while( scanf("%d", &n) !=EOF ) { ans = 0, i = -1; while( n-- ) { scanf("%d %d %d %d", &x1, &y1, &x2, &y2); scan[++i].x = x1; scan[i].y1 = y1; scan[i].y2 = y2; scan[i].flag = 1; y[i+1] = y1; scan[++i].x = x2; scan[i].y1 = y1; scan[i].y2 = y2; scan[i].flag = 0; y[i+1] = y2; } int count = i+1; qsort( scan, count, sizeof(scan[0]), cmp1 ); qsort( y+1, count, sizeof(y[1]), cmp2 ); int unique_cnt = unique( y+1, y+1+count ) - y - 1; //unique 所有的纵坐标
build( 1, unique_cnt, 1 ); int pre_sum, pre_line ; for( int j=0; j) { update( scan[j].y1, scan[j].y2, 1, scan[j].flag ); if(j >= 1) { ans += 2*pre_line*( scan[j].x - scan[j-1].x ); ans += ABS(tree[1].sum - pre_sum); //跟之前的对比!!很巧妙!!
} else ans += tree[1].sum ; pre_sum = tree[1].sum ; pre_line = tree[1].line ; } printf("%d\n", ans); } return 0; }