hdu 1828 线段树扫描线(周长)
Picture
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3897 Accepted Submission(s): 1978
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.
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.
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
First
/*
hdu 1828 线段树扫描线(周长) 给你一些矩阵,有部分or全部重叠.求最终图形的周长 对于x轴的边,矩阵的下边标为1,矩阵的上边标为-1.每次插入后用当前覆盖面积
减去上一次的覆盖面积(即新增长度),扫描过一个矩阵的上边后便能消除下边的
影响。
对x,y轴分别扫描一次即可 最开始没考虑重边的问题,结果C++ AC(G++ WR)
然后更改后G++才过 - - 2
0 0 1 1
1 0 2 1 2
0 0 1 1
0 1 1 2 hhh-2016-03-26 16:35:21
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
using namespace std;
#define lson (i<<1)
#define rson ((i<<1)|1)
typedef long long ll;
const int maxn = 20050;
int a[maxn];
struct node
{
int l,r;
int sum,len;
int mid()
{
return (l+r)>>1;
}
} tree[maxn*5]; void push_up(int i)
{
if(tree[i].sum)
tree[i].len = (tree[i].r-tree[i].l+1);
else if(tree[i].l == tree[i].r)
tree[i].len = 0;
else
tree[i].len = tree[lson].len+tree[rson].len;
} void build(int i,int l,int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].sum = 0;
tree[i].len = 0;
if(l == r)
return ; int mid = tree[i].mid();
build(lson,l,mid);
build(rson,mid+1,r);
push_up(i);
} void push_down(int i)
{
// if(tree[i].sum)
// {
// tree[lson].sum += tree[i].sum;
// tree[rson].sum += tree[i].sum;
// tree[lson].len = tree[lson].r-tree[lson].l;
// tree[rson].len = tree[rson].r-tree[rson].l;
// }
} void Insert(int i,int l,int r,int val)
{
if(tree[i].l >= l && tree[i].r <=r )
{
tree[i].sum += val;
push_up(i);
return ;
}
int mid = tree[i].mid();
push_down(i);
if(l <= mid)
Insert(lson,l,r,val);
if(r > mid)
Insert(rson,l,r,val);
push_up(i);
} struct edge
{
int l,r;
int va,high;
};
edge tx[maxn*2];
edge ty[maxn*2]; bool cmp(edge a,edge b)
{
if(a.high != b.high)
return a.high < b.high;
else //如果有重边则要先插入在删除
return a.va > b.va;
} int main()
{
int n;
while(scanf("%d",&n) != EOF)
{
int x1,x2,y1,y2;
int tox = 0,lx=0x3f3f3f3f,rx=0;
int toy = 0,ly=0x3f3f3f3f,ry=0;
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
lx = min(x1,lx),rx = max(rx,x2);
ly = min(y1,ly),ry = max(ry,y2);
tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y1,tx[tox++].va=1;
tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y2,tx[tox++].va=-1;
ty[toy].l = y1,ty[toy].r = y2,ty[toy].high=x1,ty[toy++].va=1;
ty[toy].l = y1,ty[toy].r = y2,ty[toy].high=x2,ty[toy++].va=-1;
}
sort(tx,tx+tox,cmp);
sort(ty,ty+toy,cmp);
int ans=0,prelen = 0;
build(1,lx,rx-1);
for(int i = 0; i < tox; i++)
{
Insert(1,tx[i].l,tx[i].r-1,tx[i].va);
ans += abs(tree[1].len-prelen);
prelen = tree[1].len;
}
//cout << ans <<endl;
build(1,ly,ry-1);
prelen = 0;
for(int i = 0; i < toy; i++)
{
Insert(1,ty[i].l,ty[i].r-1,ty[i].va);
ans += abs(tree[1].len-prelen);
prelen = tree[1].len;
}
cout << ans <<endl;
}
return 0;
}
Second
/*
hdu 1828 线段树扫描(周长)2 在向上扫描的过程中我们可以计算出平行于x轴的长度
然后在两条线之间我们只需要计算出有多少条竖线便能得带这两条线之间平行于
y轴的长度。
用ls和rs来表示当前节点左右端点是否被覆盖
在处理竖线数量时,注意合并带来的影响,假设lson.rs和rson.ls都存在值的话
说明存在重叠的部分 hhh-2016-03-26 17:58:50
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
using namespace std;
#define lson (i<<1)
#define rson ((i<<1)|1)
typedef long long ll;
const int maxn = 20050;
int a[maxn];
struct node
{
int l,r;
int sum,len;
int num,ls,rs;
int mid()
{
return (l+r)>>1;
}
} tree[maxn*5]; void push_up(int i)
{
if(tree[i].sum)
{
tree[i].len = (tree[i].r-tree[i].l+1);
tree[i].ls = tree[i].rs = 1;
tree[i].num = 1;
}
else if(tree[i].l == tree[i].r)
{
tree[i].len= 0;
tree[i].num=tree[i].rs=tree[i].ls=0;
}
else
{
tree[i].len = tree[lson].len+tree[rson].len;
tree[i].ls = tree[lson].ls;
tree[i].rs = tree[rson].rs;
tree[i].num = tree[lson].num+tree[rson].num;
tree[i].num -= (tree[lson].rs&tree[rson].ls);
//减去重叠的部分
}
} void build(int i,int l,int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].sum = tree[i].len = 0;
tree[i].ls = tree[i].rs = tree[i].num = 0;
if(l == r)
return ; int mid = tree[i].mid();
build(lson,l,mid);
build(rson,mid+1,r);
push_up(i);
} void push_down(int i)
{ } void Insert(int i,int l,int r,int val)
{
if(tree[i].l >= l && tree[i].r <=r )
{
tree[i].sum += val;
push_up(i);
return ;
}
int mid = tree[i].mid();
push_down(i);
if(l <= mid)
Insert(lson,l,r,val);
if(r > mid)
Insert(rson,l,r,val);
push_up(i);
} struct edge
{
int l,r;
int va,high,id;
};
edge tx[maxn*2]; bool cmp(edge a,edge b)
{
if(a.high != b.high)
return a.high < b.high;
else
return a.va > b.va;
} int main()
{
int n;
while(scanf("%d",&n) != EOF)
{
int x1,x2,y1,y2;
int tox = 0,lx=0x3f3f3f3f,rx=0;
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
lx = min(x1,lx),rx = max(rx,x2);
tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y1,tx[tox++].va=1;
tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y2,tx[tox++].va=-1;
}
sort(tx,tx+tox,cmp);
int ans=0,prelen = 0;
build(1,lx,rx-1);
//tx[tox] = tx[tox+1];
for(int i = 0; i < tox; i++)
{
Insert(1,tx[i].l,tx[i].r-1,tx[i].va);
ans += abs(tree[1].len-prelen);
if(i != tox-1)
ans += (tx[i+1].high-tx[i].high)*tree[1].num*2;
prelen = tree[1].len;
}
cout << ans <<endl;
}
return 0;
}
hdu 1828 线段树扫描线(周长)的更多相关文章
- HDU 1828 线段树+扫描线(计算矩形周长并)
题意:给你n个矩形,然后矩形有可能重叠,要你求周长 思路:首先碰到这种矩形在数轴上那么第一反应应该想到的是扫描线, 做周长我们有两种方法 第一种,我们可以分开两部分求,第一遍求x轴上的贡献,第二遍求y ...
- hdu 4052 线段树扫描线、奇特处理
Adding New Machine Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 5091(线段树+扫描线)
上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...
- HDU 5107 线段树扫描线
给出N个点(x,y).每一个点有一个高度h 给出M次询问.问在(x,y)范围内第k小的高度是多少,没有输出-1 (k<=10) 线段树扫描线 首先离散化Y坐标,以Y坐标建立线段树 对全部的点和询 ...
- hdu 1542 线段树+扫描线 学习
学习扫描线ing... 玄学的东西... 扫描线其实就是用一条假想的线去扫描一堆矩形,借以求出他们的面积或周长(这一篇是面积,下一篇是周长) 扫描线求面积的主要思想就是对一个二维的矩形的某一维上建立一 ...
- hdu 1255(线段树 扫描线) 覆盖的面积
http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所 ...
- HDU 5091 线段树扫描线
给出N个点.和一个w*h的矩形 给出N个点的坐标,求该矩形最多能够覆盖多少个点 对每一个点point(x.y)右边生成相应的点(x+w,y)值为-1: 纵向建立线段树,从左到右扫描线扫一遍.遇到点则用 ...
- hdu 4419 线段树 扫描线 离散化 矩形面积
//离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...
- hdu 3265 线段树扫描线(拆分矩形)
题意: 给你n个矩形,每个矩形上都有一个矩形的空洞,所有的矩形都是平行于x,y轴的,最后问所有矩形的覆盖面积是多少. 思路: 是典型的矩形覆盖问题,只不过每个矩形上多了一个矩 ...
随机推荐
- NumPy简介
NumPy是什么? NumPy(Numerrical Python 的缩写)是一个开源的Python科学计算库.使用NumPy,就可以很自然的使用数组.NumPy包含很多实用的数学函数,涵盖线性代数运 ...
- 【iOS】swift-通过JS获取webView的高度
let webHeightStr = webView.stringByEvaluatingJavaScriptFromString("document.body.scrollHeight& ...
- C# reportview 按时间改变行颜色
//) AND ((Day(Now()) - Day() AND (Day(Now()) - Day()),) AND (Day(Now()) - Day()) OR (Month(Now()) - ...
- javascript中数组的深拷贝的方法
一.什么是浅拷贝 在js当中,我们常常遇到数组复制的的情况,许多人一般都会使用"="来直接把一个数组赋值给一个变量,如 var a=[1,2,3]; var b=a; consol ...
- JS判断不同操作系统显示不同样式css
<script type="text/javascript"> var system ={}; var p = navigator.platform; //判断是否为P ...
- SpringBoot的注解:@SpringBootApplication注解 vs @EnableAutoConfiguration+@ComponentScan+@Configuration
spring Boot开发者经常使用@Configuration,@EnableAutoConfiguration,@ComponentScan注解他们的main类, 由于这些注解如此频繁地一块使用( ...
- jquery中attr与prop的区别
先从一个老生常谈的问题说起,使用jquery实现全选全不选.楼主先使用的jquery版本是 jquery-1.11.1.min.js 全选<input type="checkbox&q ...
- python flask框架 蓝图的使用
蓝图的目的是实现 各个模块的视图函数写在不同的py文件当中. 主视图 中 导入 分路由视图的模块,并且注册蓝图对象 分路由视图中 利用 蓝图对象 的route 进行装饰视图函数 主路由视图函数: #c ...
- 【已解决】React中配置Sass引入.scss文件无效
React中配置Sass引入.scss文件无效 在react中使用sass时,引入.scss文件失效 尝试很多方法没法解决,最终找到解决方法,希望能帮助正在坑里挣扎的筒子~ 在node_modules ...
- 关于 Integer 值比较的问题
今天刚好遇到这样的问题,别的不说,先上代码 public class TestInteger { public static void main(final String[] args) { fina ...