codevs 2149 矩形周长

这个还是扫描线。注意:维护有多少个连续的区间的时候维护l,r分别代表左端点开始是否有线段,右端点开始(向左)是否有线段。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 100005
using namespace std;
struct tree
{
int left,right;
int sum,cnt,q,l,r;
};
struct seg
{
int x1,x2,h;
int flag;
};
tree node[maxn];
seg s[maxn];
int n,a,b,c,d,tot=0,hash[maxn],father[maxn],rec=0;
bool cmp(seg x,seg y)
{
if (x.h==y.h)
return x.flag>y.flag;
else return x.h<y.h;
}
void build(int i,int left,int right)
{
node[i].left=left;
node[i].right=right;
node[i].sum=0;
node[i].cnt=0;
node[i].q=0;
node[i].l=0;
node[i].r=0;
if (left==right)
{
father[left]=i;
return;
}
int mid=(left+right)>>1;
i=i<<1;
build(i,left,mid);
build(i|1,mid+1,right);
}
int find(int x)
{
int l=1,r=2*n;
for (;;)
{
int mid=(l+r)>>1;
if (hash[mid]==x) return mid;
else if (hash[mid]<x) l=mid+1;
else r=mid-1;
}
}
void pushup1(int i)
{
int left=node[i].left,right=node[i].right;
if (node[i].q>0) node[i].sum=hash[right+1]-hash[left];
else if (left==right) node[i].sum=0;
else node[i].sum=node[i<<1].sum+node[i<<1|1].sum;
}
void pushup2(int i)//danger!
{
int left=node[i].left,right=node[i].right;
if (node[i].q>0)
{
node[i].l=1;
node[i].r=1;
node[i].cnt=1;
}
else if (left==right)
{
node[i].l=0;
node[i].r=0;
node[i].cnt=0;
}
else
{
node[i].l=node[i<<1].l;
node[i].r=node[i<<1|1].r;
node[i].cnt=node[i<<1].cnt+node[i<<1|1].cnt;
if ((node[i<<1].r==1) && (node[i<<1|1].l==1))
node[i].cnt--;
}
}
void pushup(int i)
{
pushup1(i);
pushup2(i);
}
void modify(int i,int l,int r,int flag)
{
int left=node[i].left,right=node[i].right;
if ((l==left) && (r==right))
{
node[i].q=node[i].q+flag;
pushup(i);
return;
}
int mid=(left+right)>>1;
if (r<=mid) modify(i<<1,l,r,flag);
else if (l>=mid+1) modify(i<<1|1,l,r,flag);
else
{
modify(i<<1,l,mid,flag);
modify(i<<1|1,mid+1,r,flag);
}
pushup(i);
}
int main()
{
scanf("%d",&n);
build(1,1,2*n);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
s[i*2-1].x1=a;s[i*2-1].x2=c;s[i*2-1].h=b;s[i*2-1].flag=1;
s[i*2].x1=a;s[i*2].x2=c;s[i*2].h=d;s[i*2].flag=-1;
hash[i*2-1]=a;hash[i*2]=c;
}
sort(s+1,s+2*n+1,cmp);
sort(hash+1,hash+2*n+1);
for (int i=1;i<=2*n-1;i++)
{
int l=find(s[i].x1),r=find(s[i].x2)-1;
modify(1,l,r,s[i].flag);
tot=tot+abs(node[1].sum-rec)+node[1].cnt*2*(s[i+1].h-s[i].h);
rec=node[1].sum;
}
tot=tot+(s[n*2].x2-s[n*2].x1);
printf("%d\n",tot);
return 0;
}

时间: 2024-10-25 04:15:50

codevs 2149 矩形周长的相关文章

2149 矩形周长

2149 矩形周长 USACO 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 大师 Master 题解 查看运行结果 题目描述 Description N(N<5000) 张矩形的海报,照片和其他同样形状的图片贴在墙上.它们的边都是垂直的或水平的.每个矩形可以部分或者全部覆盖其他矩形.所有的矩形组成的集合的轮廓称为周长.写一个程序计算周长. 图 1 是一个有 7 个矩形的例子: 图 1.一个 7 个矩形的集合 对应的轮廓为图 2 所示的所有线段的集合: 图 2. 矩形集合的轮廓

HDU 1828 Picture(矩形周长并)

HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4个方向都加完就是答案 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 5005; int n; struct Rec { int

25.按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有

package zhongqiuzuoye; public class Rect { public double width; public double height; Rect(double width,double height) //带有两个参数的构造方法,用于将width和height属性初化; { this.width=width; this.height=height; } Rect() //不带参数的构造方法,将矩形初始化为宽和高都为10. { width=10; height=

hdu1828 (Picture) &amp;poj 1177( Picture)&amp;sdibt 2390(5.5.1 Picture 矩形周长)(线段树+扫描)

题目地址:hdu1828 (Picture)  & poj 1177( Picture) & sdibt 2390(5.5.1 Picture 矩形周长) 题目大意: 给你N个矩形,求出N个矩形构成的周长. 解题思路: 线段数+扫描线. 推荐博客: POJ1177 Picture(线段树求轮廓周长) POJ 1177 Picture (线段树+离散化+扫描线) 详解 注意事项: 该题在求面积的基础上有了升级,多写了一个被调需要求出投影与Y轴有几段,不然样例会少算20,就是给出图形中间的小矩

扫描线矩形周长的并 POJ1177

1 //扫描线矩形周长的并 POJ1177 2 // 我是按x轴 3 4 #include <iostream> 5 #include <cstdio> 6 #include <cstdlib> 7 #include <algorithm> 8 #include <vector> 9 #include <cmath> 10 #include <cstring> 11 // #include <memory.h>

HDU 1828 扫描线(矩形周长并)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3310    Accepted Submission(s): 1723 Problem Description A number of rectangular posters, photographs and other pictures of the same shape

HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 num: 此区间分离开的线段的条数 重点在转移的地方,不难理解. 代码: #include <iostream> #include <cmath> #include <iostream> #include <cstdio> #include <cstrin

poj 1177 Picture(扫描线+矩形周长并)

http://poj.org/problem?id=1177 求矩形的周长并,明确的一点是对于覆盖的边的长度忽略不计. 与求面积并类似,首先离散化,对矩形的每条横边从下往上扫描.扫描过程中要完成三个任务,更新相应的区间信息,求横边长,求竖边长. 节点信息: l,r:左右区间编号 cnt:表示该区间是否被完全覆盖.cnt > 0 表示完全覆盖,否则不完全覆盖. lp,rp:表示该区间的两个端点是否被覆盖,为1被覆盖,为0没被覆盖. num:该区间被覆盖的线段数目.例如区间[1,10],当更新[2,

按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有确定位

package com.hanqi.test; public class Rect { public double width; public double height; //创建有参构造方法 Rect(double width,double height) { this.width=width; this.height=height; } //创建无参构造方法 Rect() { } //构建成员方法,获取周长和面积 public double getZhouchang() { return