POJ 3832 Posters

来源:互联网 发布:淘宝男装免费代理 编辑:程序博客网 时间:2024/06/05 03:06

题目大意:

题目链接

注释代码:

/*                                                 * Problem ID : POJ 3832 Posters * Author     : Lirx.t.Una                                                 * Language   : G++                                * Run Time   : 500 ms                                                 * Run Memory : 8500 KB                                                */ #pragma G++ optimize("O2")#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>//海报的最大数量#defineMAXPOSN50000//横坐标的最大值#defineMAXCORD50000//线段树的根结点指针#defineROOT1//底边bottom为1,定边top为-1#defineBTOM1#defineTOP-1//求树tree的左右子树(都是指针值)#defineLFT(TREE)( (TREE) << 1 )#defineRHT(TREE) ( LFT(TREE) | 1 )using namespace std;typedef__int64llg;//最后面积可能会超出int值structScan {//扫描线,和x轴平行intx1, x2;//左右端点inty;//高度charv;//类型,也为值value,即botm还是topbooloperator<(const Scan &oth)const {//对扫描线按照从低到高排序,尽量将底边排在前面if ( y == oth.y ) return v > oth.v;return y < oth.y;}};//以下两个数组构成虚线段树//共同维护一个线段树的两个域//由于只取每个结点所代表线段的长度因此不需要记录  //结点所代表的线段的左右区间端点intval[MAXPOSN * 4];//每个结点的重叠值intlen[MAXPOSN * 4];//每个结点的长度Scanscn[MAXPOSN * 8];//扫描线,每个回字都分为上下左右四块//因此一个回字最多有8条横向扫描线intm;//扫描线的条数intmax_cord, min_cord;//找出所有扫描线中的最左端点和最右端点//以这两个值作为根结点线段的左右端点,可以有效降低线段树的规模,并//降低二分次数(即时间复杂度)voidadd( int x1, int x2, int y, int v ) {//添加扫描线scn[m].x1 = x1;scn[m].x2 = x2;scn[m].y  = y;scn[m].v  = (char)v;m++;}voidchg_mx( int x1, int x2 ) {//对max_cord, min_cord进行跟新if ( x1 < min_cord ) min_cord = x1;if ( x2 > max_cord ) max_cord = x2;}voidcal_len( int tree, int lft, int rht ) {//calculate length//计算tree结点所代表线段的长度//传统算法//lft和rht为tree结点所代表的线段的区间if ( val[tree] ) len[tree] = rht - lft;elseif ( 1 + lft == rht ) len[tree] = 0;else len[tree] = len[ LFT(tree) ] + len[ RHT(tree) ];}voidupdate( int tree, int lft, int rht, int al, int ar, int av ) {//传统的线段树update//只不过结点的区间由传参lft和rht指定//而跟新区间为adding lft和adding rht,即al和ar//跟新进来的扫描线的类型为adding value,即avif ( lft == al && ar == rht ) {val[tree] += av;cal_len( tree, lft, rht );return ;}intmid;mid = ( lft + rht ) >> 1;if ( ar <= mid ) update( LFT(tree), lft, mid, al, ar, av );else if ( al >= mid ) update( RHT(tree), mid, rht, al, ar, av );else {update( LFT(tree), lft, mid, al, mid, av );update( RHT(tree), mid, rht, mid, ar, av );}cal_len( tree, lft, rht );}intmain() {intn;//回字的个数intx1, y1;//外左下角intx2, y2;//外右上角intx3, y3;//内左下角intx4, y4;//内右上角inti;//计数变量llgans;//最终阴影部分面积while ( scanf("%d", &n), n ) {//初始化m = 0;memset(val, 0, sizeof(val));memset(len, 0, sizeof(len));max_cord = -1;min_cord = MAXCORD + 1;while ( n-- ) {scanf("%d%d%d%d%d%d%d%d", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4);if ( x1 != x3 ) {//空心是否和左边重合add( x1, x3, y1, BTOM );add( x1, x3, y2, TOP );chg_mx( x1, x3 );}if ( x4 != x2 ) {//空心是否和右边重合add( x4, x2, y1, BTOM );add( x4, x2, y2, TOP );chg_mx( x4, x2 );}if ( y1 != y3 ) {//空心是否和下边重合add( x3, x4, y1, BTOM );add( x3, x4, y3, TOP );}if ( y4 != y2 ) {//空心是否和上边重合add( x3, x4, y4, BTOM );add( x3, x4, y2, TOP );}chg_mx( x3, x4 );//对于上下两种情况只要计算一次即可}sort(scn, scn + m);//从低到高排序ans = 0;i   = 0;while ( i < m ) {do {update( ROOT, min_cord, max_cord, scn[i].x1, scn[i].x2, scn[i].v );i++;} while ( i < m && scn[i].y == scn[i - 1].y );//先将同一高度的扫描线updateif ( i < m )//累加一次面积ans += (llg)len[ROOT] * (llg)( scn[i].y - scn[i - 1].y );}printf("%I64d\n", ans);}return 0;}

无注释代码:

#pragma G++ optimize("O2")#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>#defineMAXPOSN50000#defineMAXCORD50000#defineROOT1#defineBTOM1#defineTOP-1#defineLFT(TREE)( (TREE) << 1 )#defineRHT(TREE) ( LFT(TREE) | 1 )using namespace std;typedef__int64llg;structScan {intx1, x2;inty;charv;booloperator<(const Scan &oth)const {if ( y == oth.y ) return v > oth.v;return y < oth.y;}};intval[MAXPOSN * 4];intlen[MAXPOSN * 4];Scanscn[MAXPOSN * 8];intm;intmax_cord, min_cord;voidadd( int x1, int x2, int y, int v ) {scn[m].x1 = x1;scn[m].x2 = x2;scn[m].y  = y;scn[m].v  = (char)v;m++;}voidchg_mx( int x1, int x2 ) {if ( x1 < min_cord ) min_cord = x1;if ( x2 > max_cord ) max_cord = x2;}voidcal_len( int tree, int lft, int rht ) {if ( val[tree] ) len[tree] = rht - lft;elseif ( 1 + lft == rht ) len[tree] = 0;else len[tree] = len[ LFT(tree) ] + len[ RHT(tree) ];}voidupdate( int tree, int lft, int rht, int al, int ar, int av ) {if ( lft == al && ar == rht ) {val[tree] += av;cal_len( tree, lft, rht );return ;}intmid;mid = ( lft + rht ) >> 1;if ( ar <= mid ) update( LFT(tree), lft, mid, al, ar, av );else if ( al >= mid ) update( RHT(tree), mid, rht, al, ar, av );else {update( LFT(tree), lft, mid, al, mid, av );update( RHT(tree), mid, rht, mid, ar, av );}cal_len( tree, lft, rht );}intmain() {intn;intx1, y1;intx2, y2;intx3, y3;intx4, y4;inti;llgans;while ( scanf("%d", &n), n ) {m = 0;memset(val, 0, sizeof(val));memset(len, 0, sizeof(len));max_cord = -1;min_cord = MAXCORD + 1;while ( n-- ) {scanf("%d%d%d%d%d%d%d%d", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4);if ( x1 != x3 ) {add( x1, x3, y1, BTOM );add( x1, x3, y2, TOP );chg_mx( x1, x3 );}if ( x4 != x2 ) {add( x4, x2, y1, BTOM );add( x4, x2, y2, TOP );chg_mx( x4, x2 );}if ( y1 != y3 ) {add( x3, x4, y1, BTOM );add( x3, x4, y3, TOP );}if ( y4 != y2 ) {add( x3, x4, y4, BTOM );add( x3, x4, y2, TOP );}chg_mx( x3, x4 );}sort(scn, scn + m);ans = 0;i   = 0;while ( i < m ) {do {update( ROOT, min_cord, max_cord, scn[i].x1, scn[i].x2, scn[i].v );i++;} while ( i < m && scn[i].y == scn[i - 1].y );if ( i < m )ans += (llg)len[ROOT] * (llg)( scn[i].y - scn[i - 1].y );}printf("%I64d\n", ans);}return 0;}

单词解释:


0 0
原创粉丝点击