【解题报告】pojP1436 Horizontally Visible Segments
http://poj.org/problem?id=1436
题目大意:有n条平行于x轴的线段,每条线段有y坐标,如果两条线段有一段x坐标数值相等,且中间没有其它线段阻隔,则称这两条线段”照面“。如果三条线段两两互能照面,则称这三条线段为一组。问这n条线段中有多少组?
可以看到题目中n<=8000,于是开始想n log n的算法,但是当我看那题的discuss时,有人说
这题数据太无语了……O(n^2lgn) TLE , O(n^3)的算法266ms……
O(n^3)能过?于是想到如果能判断并保存两两线段之间的是否照面关系,然后n*n*n暴力搜索互相照面的三条线段。。。
现在问题只剩下如何判断并保存两两线段之间的是否照面关系了,这就是典型的线段树区间覆盖问题
1、先把所有线段按x坐标排一下序
2、线段树a[i].l表示左边界,a[i].r表示右边界,a[i].n表示占据该区域的线段号码,建树
3、压过程:把线段从树顶压下去,若碰到延迟标记就顺便压下子树,若碰到a[i].n!=0的子树,mark[a[i].n][x(目前压的线段号)]=1
4、冲过程:把线段加入线段树,找到属于该线段的区间(顺路推下延迟标记),若发现该区间a[i].n!=0,直接覆盖掉!因为线段已经被排过序,所以从宏观上看,就是x坐标大的线段把x坐标小的线段挡住了,以后的线段也不会再在该区间与x坐标小的线段照面了(想的时候在这里卡了很长时间)
5、回到第三步,直到所有线段都经过了冲压过程
6、O(n^3)暴力搜索互相照面的三条线段
我的程序:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
bool mark[][];
int n; struct
{
int l,r,n;
} a[*]; struct node
{
int x,y1,y2;
} s[]; int cmp(node a,node b)
{
return a.x<b.x;
} void build(int l,int r,int i)
{
a[i].l=l;
a[i].r=r;
a[i].n=;
if(l==r) return;
int k=(l+r)/;
build(l,k,*i);
build(k+,r,*i+);
} void add(int l,int r,int i,int m)
{
if ((l<=a[i].l)&&(a[i].r<=r))
{
a[i].n=m;
return;
}
if (a[i].n!=-)
{
a[*i].n=a[*i+].n=a[i].n;
a[i].n=-;
}
if (l<=a[*i].r)
add(l,r,*i,m);
if (r>=a[*i+].l)
add(l,r,*i+,m);
} void push(int l,int r,int i,int m)
{
if (a[i].n!=-)
{
mark[a[i].n][m]=;
return;
}
if ((a[i].l)==(a[i].r)) return;
if (a[i].n!=-)
{
a[*i].n=a[*i+].n=a[i].n;
a[i].n=-;
}
if (l<=a[*i].r) push(l,r,*i,m);
if (r>=a[*i+].l) push(l,r,*i+,m);
}
void show()
{
int i,j,k;
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
printf ("%d ",mark[i][j]);
printf ("\n");
}
}
int main()
{
int t,ans,i,x,y1,y2,j,k;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=;i<=n;i++)
{
scanf("%d%d%d",&s[i].y1,&s[i].y2,&s[i].x);
s[i].y1*=;
s[i].y2*=;
}
sort(s+,s++n,cmp);
memset(mark,false,sizeof(mark));
build(,,);
for(i = ; i<=n; i++)
{
push(s[i].y1,s[i].y2,,i);
add(s[i].y1,s[i].y2,,i);
show();
printf ("\n");
}
ans=;
for(i=;i<=n;i++)
for(j=;j<=n;j++)
if (mark[i][j]) for (k=;k<=n;k++) if ((mark[i][k])&&(mark[j][k])) ans++;
printf("%d\n",ans);
}
}
【解题报告】pojP1436 Horizontally Visible Segments的更多相关文章
- POJ 1436 Horizontally Visible Segments (线段树·区间染色)
题意 在坐标系中有n条平行于y轴的线段 当一条线段与还有一条线段之间能够连一条平行与x轴的线不与其他线段相交 就视为它们是可见的 问有多少组三条线段两两相互可见 先把全部线段存下来 并按x ...
- POJ 1436 Horizontally Visible Segments(线段树)
POJ 1436 Horizontally Visible Segments 题目链接 线段树处理染色问题,把线段排序.从左往右扫描处理出每一个线段能看到的右边的线段,然后利用bitset维护枚举两个 ...
- poj 1436 && zoj 1391 Horizontally Visible Segments (Segment Tree)
ZOJ :: Problems :: Show Problem 1436 -- Horizontally Visible Segments 用线段树记录表面能被看见的线段的编号,然后覆盖的时候同时把能 ...
- (中等) POJ 1436 Horizontally Visible Segments , 线段树+区间更新。
Description There is a number of disjoint vertical line segments in the plane. We say that two segme ...
- 【37%】【poj1436】Horizontally Visible Segments
Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 5200 Accepted: 1903 Description There ...
- POJ 1436 Horizontally Visible Segments
题意: 有一些平行于y轴的线段 ,两条线段称为互相可见当且仅当存在一条水平线段连接这两条 与其他线段没交点. 最后问有多少组 3条线段,他们两两是可见的. 思路: 线段树,找出两两可见的那些组合, ...
- POJ 1436 (线段树 区间染色) Horizontally Visible Segments
这道题做了快两天了.首先就是按照这些竖直线段的横坐标进行从左到右排序. 将线段的端点投影到y轴上,线段树所维护的信息就是y轴区间内被哪条线段所覆盖. 对于一条线段来说,先查询和它能相连的所有线段,并加 ...
- poj1436 Horizontally Visible Segments
这是一个区间更新的题目,先将区间放大两倍,至于为什么要放大可以这样解释,按照从左到右有4个区间,y值是[1,5],[1,2],[3,4],[1,4]如果不放大的话,查询[1,4]区间和前面区间的”可见 ...
- POJ 1436.Horizontally Visible Segments-线段树(区间更新、端点放大2倍)
水博客,水一水. Horizontally Visible Segments Time Limit: 5000MS Memory Limit: 65536K Total Submissions: ...
随机推荐
- MySQL5.6自动化部署(二进制)
###### 二进制自动安装数据库脚本root密码MANAGER将脚本和安装包放在/root目录即可############### ######数据库目录/usr/local/mysql####### ...
- ORACLE Postgresql中文排序
当我们order排序不能够实现我们想要的内容时候,尝试一下NLSSORT这个函数吧 他不仅仅按照姓氏排序,名也会排序: nls_param用于指定语言特征,格式为nls_sort = sor ...
- 超棒的30款JS类库和工具
http://www.csdn.net/article/2013-07-01/2816068-best-javascript-libraries-and-tools
- PHP扩展之多线程
PHP一直以为不支持多线程,后面才知道有基于pThread的扩展包,地址如下: http://php.net/manual/zh/book.pthreads.php 我感兴趣的是以下几个点: 1.Th ...
- 微信扫码下载APP
前段时间开发过程中,要实现一个扫描二维码下载APP的功能,但是苹果系统中,微信不可以直接跳转苹果商店,需要先下载应用宝,显然太麻烦... 这样我们可以做个中间页,用中间页面生成二维码链接,在中间页代码 ...
- FP Tree算法原理总结
在Apriori算法原理总结中,我们对Apriori算法的原理做了总结.作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈.为了解决这个问题,FP Tree算法(也称F ...
- 在Oracle中数据库、表空间、表之间的关系
在oracle中,表空间是存储概念上的,建立表空间需要有对应的数据文件,数据文件建立好之后直接会把一定的磁盘空间分配给它,这样可以对数据库的存储空间进行有效的管理.然后在建表的时候指定对应的表空间,该 ...
- MySQL 存储表情字符
摘要 在 MySQL 中直接存储表情的时候,会出现无法插入数据的错误. 这是由于一般情况下,MySQL 的字符集是 utf8,而对于 emoji 表情的 mysql 的 utf8 字符集是不支持,需要 ...
- 微端启动器LAUNCHER的制作之MFC版二(下载)
用了C#再回来用C++写真的有一种我已经不属于这个世界的感觉.C++的下载就没有C#那么方便了,我用的是libcurl.dll,官网上下载的源码自己cmake出来编译的,c++的库引用有debug和r ...
- HTTP严格安全传输(HTTP Strict Transport Security, HSTS)chromuim实现源码分析(一)
// HTTP strict transport security (HSTS) is defined in// http://tools.ietf.org/html/ietf-websec-stri ...