【题】【线段树(lazy)】NKOJ 1868 矩形周长【USACO5.5.1】Picture
来源:互联网 发布:广州优化网站 编辑:程序博客网 时间:2024/06/06 09:44
NKOJ 1868 【USACO5.5.1】Picture矩形周长
时间限制 : 10000 MS 空间限制 : 65536 KB
问题描述
N(N<5000) 张矩形的海报,照片和其他同样形状的图片贴在墙上。它们的边都是垂直的或水平的。每个矩形可以部分或者全部覆盖其他矩形。所有的矩形组成的集合的轮廓称为周长。写一个程序计算周长。
图 1 是一个有 7 个矩形的例子:
图 1.一个 7 个矩形的集合
对应的轮廓为图 2 所示的所有线段的集合:
图 2. 矩形集合的轮廓
所有矩形的顶点坐标均为整数。所有的坐标都在 [-10000,10000] 的范围内,并且任何一个矩形面积都为整数。结果的值可能需要 32 位有符号整数表示。
输入格式
第1行: N,张贴在墙上的矩形的数目。 第 2..N+1行 接下来的N行中,每行都有两个点的坐标,分别是矩形的左下角坐标和右上角坐标。每一个坐标由 X 坐标和 Y 坐标组成。
输出格式
只有一行,为一个非负整数,表示输入数据中所有矩形集合的轮廓长度。
样例输入
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
样例输出
228
思路:
1、将所有矩形看作四条边
2、对于每条横向边,按纵坐标排序,依次讨论,若讨论的为某个矩形靠下的一条边,ans+=将这条边覆盖在线段树上前后,该边覆盖区间内被覆盖数之差。若为靠上的一条边ans+=将这条边之前的一条对应边删除前后,该边覆盖区间内被覆盖数之差。
3、lazy表示覆盖的状态。
代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstdlib>using namespace std;const int need=20003;struct yf{int x1,y1,x2,y2;short cnt;}sq[10003];struct fy{int a,b,lazy;}t[need*2];//int le[need*2],ri[need*2];int tot=0,x,y;bool cy(yf a,yf b){ int s1=a.cnt==1?a.y1:a.y2,s2=b.cnt==1?b.y1:b.y2; return s1<s2;}bool cx(yf a,yf b){ int s1=a.cnt==1?a.x1:a.x2,s2=b.cnt==1?b.x1:b.x2; return s1<s2;}void build(int x,int y){ int s=++tot; t[s].a=x,t[s].b=y; if(x+1==y) return ; le[s]=tot+1;build(x,(x+y)>>1); ri[s]=tot+1;build((x+y)>>1,y);}void putdown(int s){ if(t[s].a+1==t[s].b) return ; int k=t[s].lazy; t[s].lazy=0; t[le[s]].lazy+=k; t[ri[s]].lazy+=k; }void cover_(int s){ if(x>t[s].b||y<t[s].a) return ; if(t[s].lazy!=0) putdown(s); if(x<=t[s].a&&t[s].b<=y) { t[s].lazy++; return ; } cover_(le[s]),cover_(ri[s]);}void clean_(int s){ if(x>t[s].b||y<t[s].a) return ; if(t[s].lazy!=0) putdown(s); if(x<=t[s].a&&t[s].b<=y) { t[s].lazy--; return ; } clean_(le[s]),clean_(ri[s]);}int cnt_(int s){ if(x>t[s].b||y<t[s].a) return 0; if(x<=t[s].a&&t[s].b<=y&&t[s].lazy>0) return t[s].b-t[s].a; if(t[s].lazy!=0) putdown(s); return cnt_(le[s])+cnt_(ri[s]);}int main(){ build(1,20000); int n;scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d%d%d",&sq[i].x1,&sq[i].y1,&sq[i].x2,&sq[i].y2); sq[i].x1+=10000,sq[i].y1+=10000,sq[i].x2+=10000,sq[i].y2+=10000; sq[i].cnt=1; sq[i+n]=sq[i]; sq[i+n].cnt=2; } sort(sq+1,sq+1+(n<<1),cy); int ans=0,cnt1,cnt2; for(int i=1,nn=n<<1;i<=nn;i++) { x=sq[i].x1,y=sq[i].x2; if(sq[i].cnt==1) { cnt1=cnt_(1); cover_(1); cnt2=cnt_(1); ans+=abs(cnt1-cnt2); } if(sq[i].cnt==2) { cnt1=cnt_(1); clean_(1); cnt2=cnt_(1); ans+=abs(cnt1-cnt2); } } for(int i=1;i<=need*2;i++) t[i].lazy=0; sort(sq+1,sq+1+(n<<1),cx); for(int i=1,nn=n<<1;i<=nn;i++) { x=sq[i].y1,y=sq[i].y2; if(sq[i].cnt==1) { cnt1=cnt_(1); cover_(1); cnt2=cnt_(1); ans+=abs(cnt1-cnt2); } if(sq[i].cnt==2) { cnt1=cnt_(1); clean_(1); cnt2=cnt_(1); ans+=abs(cnt1-cnt2); } } printf("%d",ans);}
0 0
- 【题】【线段树(lazy)】NKOJ 1868 矩形周长【USACO5.5.1】Picture
- 洛谷 P1856 [USACO5.5]矩形周长Picture
- HUD 1828 Picture 矩形周长/线段树
- 线段树 矩形并周长 picture
- 【HDU1828】Picture【线段树】【矩形周长并】
- poj 1177 Picture(线段树求矩形周长并)
- POJ1177 HDU1828 Picture,线段树求矩形并周长
- hdu1828 Picture(扫描线+矩形周长并+线段树)
- Hdu 1828 Picture 线段树+矩形周长并
- poj 1177 Picture(线段树+矩形周长并)
- hdu 1828 Picture 线段树 矩形周长并
- 【poj1177】Picture(矩形周长并+线段树+扫描线)
- hdu1828 Picture(线段树+扫描线+矩形周长并)
- POJ-1177 Picture (线段树 求矩形周长)
- 线段树 矩形周长
- USACO5.5.1 Picture (picture)
- USACO5.5.1 Picture(picture)
- hdu 1828 / poj/pku 1177(Picture)(线段树求矩形覆盖面周长)
- BEEGO session写入,读取
- jquery实现点击div空白处隐藏该div
- Oracle RAC的五大优势及其劣势
- C++中模板的特化与偏特化
- HDU 2660 Accepted Necklace
- 【题】【线段树(lazy)】NKOJ 1868 矩形周长【USACO5.5.1】Picture
- PAT 甲级 1060 Are They Equal
- windows/linux + java + jna + dll/so 调用C/C++
- JQuery 树形表格插件使用
- Swift利用闭包(closure)来实现传值-->前后两个控制器的反向传值
- hdu 1503
- 核方法(kernel method)的主要思想
- hive教程
- 4步win7下简单FTP服务器搭建(试验成功)