POJ 1177 Picture(线段树+扫描线)
来源:互联网 发布:android 离线数据缓存 编辑:程序博客网 时间:2024/06/05 09:53
Description
求n个矩形的周长并
Input
第一行为一整数n表示矩形个数,之后n行每行四个整数x1,y1,x2,y2表示该矩形左下端点与右上端点的横纵坐标
Output
输出这n个矩形的周长并
Sample Input
7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16
Sample Output
228
Solution
类似矩形面积并,首先用左右两边表示一个矩形并标记每条线段是左边还是右边,然后对这些线段按x升序排序,对y轴建树(对每个线段的两端点纵坐标排完序离散化之后建线段树),用一根扫描线从左往右扫这些线段,线段树记录的是当前区间中有多少段不连续的已经被扫描的区间,被完全覆盖的次数,左右端点是否被覆盖,被覆盖的长度,每次扫描线扫到左边就在线段树中覆盖这个区间,遇到右端点就取消这段区间的覆盖,维护这个区间中被连续覆盖部分的数量乘二倍的相邻扫描线间距即为这次扫描部分横边的长度,这个区间被覆盖的长度减去上一根扫描线被覆盖长度的绝对值即为这次扫描部分纵边的长度,具体如何维护见代码
Code
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<cmath>using namespace std;#define maxn 11111struct Tree{ int left,right,num,flag,len; bool lf,rf;}T[4*maxn];//num表示这个区间被连续覆盖部分的数量 //flag标记这个区间是否被完全覆盖//len表示这个区间被覆盖的长度//lf和rf表示这个区间的左右端点是否被覆盖 struct Line{ int x,y1,y2; bool flag;}line[maxn];int n,cnt,res,y[maxn],ans,num,len;void add(int x,int y1,int y2,int yy,int flag){ line[cnt].x=x;line[cnt].y1=y1;line[cnt].y2=y2;line[cnt].flag=flag;y[cnt++]=yy;}bool cmp(Line l1,Line l2){ if(l1.x!=l2.x) return l1.x<l2.x; return l1.flag>l2.flag;}void build(int l,int r,int t){ T[t].left=l; T[t].right=r; T[t].num=T[t].len=T[t].flag=T[t].lf=T[t].rf=0; if(l+1==r)return ; int mid=(l+r)>>1; build(l,mid,2*t); build(mid,r,2*t+1);} void update_num(int t){ if(T[t].flag) T[t].lf=T[t].rf=T[t].num=1; else if(T[t].left+1==T[t].right) T[t].lf=T[t].rf=T[t].num=0; else { T[t].lf=T[2*t].lf; T[t].rf=T[2*t+1].rf; T[t].num=T[2*t].num+T[2*t+1].num-T[2*t].rf*T[2*t+1].lf; }}void update_len(int t){ if(T[t].flag) T[t].len=y[T[t].right]-y[T[t].left]; else if(T[t].left+1==T[t].right) T[t].len=0; else T[t].len=T[2*t].len+T[2*t+1].len;}void update(int l,int r,int z,int t){ if(y[T[t].left]==l&&y[T[t].right]==r) T[t].flag+=z; else if(T[t].left+1==T[t].right) return ; else { int mid=(T[t].left+T[t].right)>>1; if(r<=y[mid]) update(l,r,z,2*t); else if(l>=y[mid]) update(l,r,z,2*t+1); else { update(l,y[mid],z,2*t); update(y[mid],r,z,2*t+1); } } update_num(t); update_len(t);}int main(){ while(~scanf("%d",&n)) { cnt=0;ans=0;len=num=0; int x1,x2,y1,y2; while(n--) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); //用左右两边表示该矩形 add(x1,y1,y2,y1,1); add(x2,y1,y2,y2,0); } sort(line,line+cnt,cmp);//对这些线段按横坐标升序排序 //对y轴建树 sort(y,y+cnt); res=unique(y,y+cnt)-y; build(0,res-1,1); for(int i=0;i<cnt;i++) { if(line[i].flag) update(line[i].y1,line[i].y2,1,1);//扫到左边就在线段树中覆盖这个区间 else update(line[i].y1,line[i].y2,-1,1);//扫到右边就在线段树中取消这个区间的覆盖 if(i) ans+=2*num*(line[i].x-line[i-1].x);//横边长度 ans+=abs(T[1].len-len);//纵边长度 len=T[1].len;//更新被覆盖的长度 num=T[1].num;//更新被连续覆盖部分的数量 } printf("%d\n",ans); } return 0;}
0 0
- POJ 1177 Picture (线段树扫描线)
- poj - 1177 - Picture(离线化+扫描线+线段树)
- POJ 1177 Picture(线段树+扫描线)
- POJ 1177:Picture(线段树-扫描线)
- POJ 1177-Picture(线段树+离散化+扫描线)
- poj 1177 Picture 线段树+离散化+线扫描
- POJ 1177 Picture (线段树+离散化+扫描线) 详解
- picture 1177 poj 线段树+扫描线+离散化
- 【线段树+扫描线】 HDOJ 1828 && POJ 1177 Picture
- POJ 1177 Picture [离散化+扫描线+线段树]
- POJ - 1177 Picture(线段树 扫描线 区间合并)
- poj 1177 Picture 【线段树 扫描线 求轮廓周长】
- POJ 1177&&HDU1828 Picture 线段树+扫描线
- HDU 1828 && POJ 1177 Picture(线段树+扫描线+离散化)
- poj 1177 || HDU 1828 Picture (线段树扫描线求 图形并的周长)
- poj-1177 Picture(矩形周长并,线段树+扫描线)
- poj 1177 picture(线段树+扫描线+离散化)★
- POJ 1177 Picture & hdu 1828 Picture(扫描线)
- 非递归实现二叉树遍历(思路+代码)
- 二分查找算法及其变种
- Python中用encoding声明的文件编码和文件的实际编码之间的关系
- ViewPager Adapter FragmentStatePagerAdapter FragmentPagerAdapter 使用详解
- 迭代器
- POJ 1177 Picture(线段树+扫描线)
- Eclipse OS X Yosemite 提示– To open“Eclipse” you need to install the legacy Java SE 6 runtime的解决办法
- pdo+mysql+php
- mybatis实战教程(mybatis in action),mybatis入门到精通
- saltstack相关的一些总结
- 把以下IP存入一个txt文件,编写程序把这些IP按数值大小,从小到达排序并打印出来。 61.54.231.245 61.54.231.9 61.54.231.246 61.54.231.48
- [Leetcode]Evaluate Reverse Polish Notation
- 【Matlab】小函数
- hdu 2108 Shape of HDU 计算几何(向量的叉积)