POJ1177 HDU1828 Picture,线段树求矩形并周长
2012-01-26 00:50
429 查看
和矩形并求面积类似,不过T_NODE中保存num、lb、rb用于记录段信息,num记录的是这个节点共有多少个不连续的段,lb、rb记录的是这个节点的上下界是否与别的节点有重合。
/******************************************************************************* # Author : Neo Fung # Email : neosfung@gmail.com # Last modified: 2012-01-25 18:57 # Filename: POJ1177 HDU1828 Picture.cpp # Description : 线段树求矩形并 ******************************************************************************/ #ifdef _MSC_VER #define DEBUG #endif #include <fstream> #include <stdio.h> #include <iostream> #include <string.h> #include <string> #include <limits.h> #include <algorithm> #include <math.h> #include <numeric> #include <functional> #include <ctype.h> #define L(x) (x<<1) #define R(x) (x<<1|1) #define MAX 5010 using namespace std; //length当前节点子树覆盖的长度 //num,当前节点子树中被分为多少段不连续的小段,用于计算平行于X轴的线段长度 //cover,标记当前节点是否被覆盖 //lb,rb,标记当前节点的左端点和右端点是否被覆盖,找num的数量需要用到。 struct T_NODE { int l,r,length,cover,num; bool lb,rb; }node[MAX<<2]; struct LINE { int x,y1,y2,flag; }line[MAX<<1]; int y_coord[MAX<<1]; void add_line(const int &x1,const int &x2,const int &y1,const int &y2,int &cnt) { line[cnt].x=x1; line[cnt].y1=y1; line[cnt].y2=y2; line[cnt].flag=1; y_coord[cnt++]=y1; line[cnt].x=x2; line[cnt].y1=y1; line[cnt].y2=y2; line[cnt].flag=-1; y_coord[cnt++]=y2; } bool inline cmp(const LINE &lhs,const LINE &rhs) { return lhs.x<rhs.x; } void init() { memset(node,0,sizeof(node)); } void build(const int &t,const int &l,const int &r) { node[t].l=l; node[t].r=r; node[t].num = 0; if(l==r-1) return; int mid=(l+r)>>1; build(L(t),l,mid); build(R(t),mid,r); } void update_len(const int &t) { if(node[t].cover>0) { node[t].num = node[t].lb =node[t].rb =1; node[t].length = y_coord[node[t].r]-y_coord[node[t].l]; } else if(node[t].l==node[t].r-1) node[t].length=node[t].num=node[t].lb=node[t].rb=0; else { node[t].length = node[R(t)].length+node[L(t)].length; node[t].rb=node[R(t)].rb; node[t].lb=node[L(t)].lb; //如果两段的端点重合,则-1 node[t].num=node[L(t)].num+node[R(t)].num - node[L(t)].rb*node[R(t)].lb; } } void update_tree(const int &t,const LINE &lne) { if(y_coord[node[t].l]>=lne.y1 && y_coord[node[t].r]<=lne.y2) { node[t].cover+=lne.flag; update_len(t); return; } if(node[t].l==node[t].r-1) return; int mid = (node[t].l+node[t].r)>>1; if(lne.y1<=y_coord[mid]) update_tree(L(t),lne); if(lne.y2>y_coord[mid]) update_tree(R(t),lne); update_len(t); } __int64 solve(const int &n,const int &cnt) { init(); build(1,0,cnt-1); __int64 sum=0ll; int last =0 ,lines=0; for(int i=0;i<n;++i) { update_tree(1,line[i]); if(i>0) sum+=2ll * lines *(line[i].x - line[i-1].x); //求平行于X轴的边的长度 sum += abs(node[1].length - last); //求平行于Y轴的边的长度 last = node[1].length; lines = node[1].num; } return sum; } int main(void) { #ifdef DEBUG freopen("../stdin.txt","r",stdin); freopen("../stdout.txt","w",stdout); #endif int n; int x1,y1,x2,y2; while(~scanf("%d",&n) && n) { int cnt=0; for(int i=0;i<n;++i) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); add_line(x1,x2,y1,y2,cnt); } sort(line,line+cnt,cmp); sort(y_coord,y_coord+cnt); int temp=unique(y_coord,y_coord+cnt)-y_coord; printf("%I64d\n",solve(cnt,temp)); } return 0; }
相关文章推荐
- 【HDU1828】Picture【线段树】【矩形周长并】
- hdu1828 Picture(扫描线+矩形周长并+线段树)
- poj1177[IOI1998]Picture (扫描线+离散化+线段树,求矩形周长并)
- hdu1828 Picture(线段树+扫描线+矩形周长并)
- hdu1828&poj1177(线段树求矩形交周长,扫描线)
- POJ 1177 Picture(扫描线 + 线段树 矩形覆盖区域周长的并)
- POJ-1177-Picture(线段树+扫描线+离散化)[矩形周长并]
- hdu 1828 Picture(线段树扫描线矩形周长并)
- hdu 1828 Picture(线段树扫描线矩形周长并)
- poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)
- hdu1828 线段树扫描线求矩形面积的周长
- [HDOJ1828]Picture(扫描线,线段树,矩形并周长)
- HUD 1828 Picture 矩形周长/线段树
- POJ - 1177/HDU - 1828 Picture(线段树-矩形并周长)
- 【题】【线段树(lazy)】NKOJ 1868 【USACO5.5.1】Picture矩形周长
- Hdu 1828 Picture 线段树+矩形周长并
- 线段树 矩形并周长 picture
- poj 1177 Picture(线段树+矩形周长并)
- HDU 1828 / POJ 1177 Picture --线段树求矩形周长并
- POJ-1177 Picture (线段树 求矩形周长)