Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 4487 Accepted Submission(s): 2209

Problem Description

A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the union of all rectangles is called the perimeter.

Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.

The corresponding boundary is the whole set of line segments drawn in Figure 2.

The vertices of all rectangles have integer coordinates.

Input

Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate.

0 <= number of rectangles < 5000

All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

Please process to the end of file.

Output

Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.

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

【题目链接】:http://acm.hdu.edu.cn/showproblem.php?pid=1828

【题解】



线段树扫描线求矩形的并周长;

cnt域仍旧是记录这个区间内下边的长度比上边多的个数;

sumhx表示这个区间横线的长度;

sumsx表示这个区间内竖线的个数(去掉在内部的线,只保留不重复的);

lsx和rsx表示这个区间内的最左边和最右边是否有竖线(用于去掉内部的线);

从下往上扫描所有的下边和上边;(把所有的边处理处理按照高度排序;)

用竖线的个数乘两条线的高度差+横线的长度;

其中横线的长度要用当前整个区间的横线长度减去上一次整个区间的横线长度的绝对值值差来搞;

/*以下内容看完代码再看:
那个区间去掉重复的竖直线的;
可以用
1-3和3-5来体会;(横坐标)
即1-3和3-5是两个连在一起的的矩形;
但是竖线只算1和5,则中间那个3会被删掉->即-=2;(因为会插入两次所以得减2); 然后是那个排序的时候,相同高度的不能直接跳过;还要安装它们的上下边的属性来排;下边要先处理;
比如下图情况
*/

//上图如果先处理下边;那个△x会被多算一次;即直接增加了x(因为这个时候上边还没被处理;减last的时候会直接加上x而不是x-△x;

【完整代码】

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <string>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long using namespace std; const int MAXN = 22000;
const int dx[5] = {0,1,-1,0,0};
const int dy[5] = {0,0,0,-1,1};
const double pi = acos(-1.0);
struct abc
{
int l,r,h,k;
}; int n,num = 0,cnt[MAXN<<2],sumhx[MAXN<<2],sumsx[MAXN<<2];
bool lsx[MAXN<<2],rsx[MAXN<<2];
abc a[MAXN]; bool cmp(abc a,abc b)
{
if (a.h==b.h)
return a.k>b.k;
return a.h < b.h;
} void push_up(int rt,int l,int r)
{
if (cnt[rt])
{
lsx[rt]=rsx[rt] = 1;
sumhx[rt] = r-l+1;
sumsx[rt] = 2;
}
else
if (l==r)
lsx[rt]=rsx[rt]=sumhx[rt]=sumsx[rt] = 0;
else
{
sumhx[rt] = sumhx[rt<<1]+sumhx[rt<<1|1];
sumsx[rt] = sumsx[rt<<1]+sumsx[rt<<1|1];
lsx[rt] = lsx[rt<<1];
rsx[rt] = rsx[rt<<1|1];
if (rsx[rt<<1] && lsx[rt<<1|1])
sumsx[rt]-=2;
}
} void up_data(int L,int R,int c,int l,int r,int rt)
{
if (L<=l && r<=R)
{
cnt[rt]+=c;
push_up(rt,l,r);
return;
}
int m = (l+r)>>1;
if (L<=m)
up_data(L,R,c,lson);
if (m < R)
up_data(L,R,c,rson);
push_up(rt,l,r);
} int main()
{
//freopen("F:\\rush.txt","r",stdin);
while (~scanf("%d",&n))
{
memset(lsx,0,sizeof(lsx));
memset(rsx,0,sizeof(rsx));
memset(sumsx,0,sizeof(sumsx));
memset(sumhx,0,sizeof(sumhx));
memset(cnt,0,sizeof(cnt));
num = 0;
int tl = 10000,tr=-10000;
for (int i = 1;i <= n;i++)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
a[++num].l = x1;a[num].r = x2;a[num].h = y1;a[num].k = 1;
a[++num].l = x1;a[num].r = x2;a[num].h = y2;a[num].k = -1;
tl = min(tl,x1);tr = max(tr,x2);
}
sort(a+1,a+1+num,cmp);
int last = 0,ans = 0;
for (int i = 1;i <= num;i++)
{
if (a[i].l<a[i].r)
up_data(a[i].l,a[i].r-1,a[i].k,tl,tr-1,1);
ans += sumsx[1]*(a[i+1].h-a[i].h);
ans += abs(sumhx[1]-last);
last = sumhx[1];
}
printf("%d\n",ans);
}
return 0;
}

【49.23%】【hdu 1828】Picture的更多相关文章

  1. 【HDU 1828】 Picture (矩阵周长并,线段树,扫描法)

    [题目] Picture Problem Description A number of rectangular posters, photographs and other pictures of ...

  2. Picture【HDU - 1828】【扫描线】

    题目链接 这道题求的是这些可能存在重叠的小方块可能构成的合成方块的周长的值是多少,有简单却会很复杂的做法就是去跑纵向和横向两次的扫描线,求得最后的两个周长和,但是这样的做法未免显得复杂了,我们完全可以 ...

  3. 【改革春风吹满地 HDU - 2036 】【计算几何-----利用叉积计算多边形的面积】

    利用叉积计算多边形的面积 我们都知道计算三角形的面积时可以用两个邻边对应向量积(叉积)的绝对值的一半表示,那么同样,对于多边形,我们可以以多边形上的一个点为源点,作过该点并且过多边形其他点中的某一个的 ...

  4. HDU 1828:Picture(扫描线+线段树 矩形周长并)

    题目链接 题意 给出n个矩形,求周长并. 思路 学了区间并,比较容易想到周长并. 我是对x方向和y方向分别做两次扫描线.应该记录一个pre变量,记录上一次扫描的时候的长度,对于每次遇到扫描线统计答案的 ...

  5. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  6. 七夕节 (HDU - 1215) 【简单数论】【找因数】

    七夕节 (HDU - 1215) [简单数论][找因数] 标签: 入门讲座题解 数论 题目描述 七夕节那天,月老来到数字王国,他在城门上贴了一张告示,并且和数字王国的人们说:"你们想知道你们 ...

  7. 【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5489 题目大意: 一个N(N<=100000)个数的序列,要从中去掉相邻的L个数(去掉整个区间 ...

  8. 【贪心】【模拟】HDU 5491 The Next (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5491 题目大意: 一个数D(0<=D<231),求比D大的第一个满足:二进制下1个个数在 ...

  9. 【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5773 题目大意: T组数据,n个数(n<=100000),求最长上升子序列长度(0可以替代任何 ...

随机推荐

  1. c++11的新特性

    好奇心来源于下面的一段代码, 一个是unordered_map, 这是c++11新加的container. 另外还有unordered_set, unordered_multimap, unorder ...

  2. TIJ——Chapter Nine:Interfaces

    A class containing abstract methods is called an abstract class. If a class Contains one of more abs ...

  3. phpexcel使用说明5----ThinkPHP+PHPExcel[导入][导出]实现方法

    转自:http://www.thinkphp.cn/code/403.html实现步骤: 注意:phpexcel必须是1.78版本的,不能用1.8以上的 一:去官网http://phpexcel.co ...

  4. header发送Cookie

    Cookie传达给客户端的原理 平时执行setcookie('key1', 'value1');这样的代码时,浏览器就会收到cookie并保存,但我们并不能从echo出去的内容中看到cookie内容 ...

  5. shell不排序去重

    一条命令搞定:   awk '!a[$0]++' file 如果是第一次出现a[$0]++的值为0(假),而!a[$0]++的值就为1(真),之后就执行print $0 第二次或者两次以上的出现a[$ ...

  6. vue-router2.0的用法

    随着vue越来越火,而vue-router却是一个项目不可或缺的,所以在这里结合实例总结一下router的用法,也是给自己的一个总结. 1.首先第一步当然是安装vue-router依赖,当然也可直接s ...

  7. Linux 运算符

    布尔运算符 下表列出了常用的布尔运算符,假定变量a为10 变量b为20: 运算符  说明 举例 ! 非运算 , 表达式为true 则返回false 否则返回true  [!false] 返回true. ...

  8. display的值和对应的意义

    none:隐藏对应元素,不为隐藏的对象保留其物理空间 block:指定对象为块元素 inline:指定对象为内联元素 inline-block:指定对象为内联块元素 table:指定对象为块元素的表格 ...

  9. 在对文件进行随机读写,RandomAccessFile类,如何提高其效率

    花1K内存实现高效I/O的RandomAccessFile类 JAVA的文件随机存取类(RandomAccessFile)的I/O效率较低.通过分析其中原因,提出解决方案.逐步展示如何创建具备缓存读写 ...

  10. pytorch中squeeze()和unsqueeze()函数介绍

    一.unsqueeze()函数 1. 首先初始化一个a 可以看出a的维度为(2,3) 2. 在第二维增加一个维度,使其维度变为(2,1,3) 可以看出a的维度已经变为(2,1,3)了,同样如果需要在倒 ...