【解题报告】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: ...
随机推荐
- Mac 电脑系统的重装
首先来说一下我为什么会想到重装Mac的系统呢??? 其实呢 很简单的一个理由,在我写上一个项目的时候,在功能code编写完成后,在模拟器上运行是完全没有问题的,但是在真机上就不行,大家也都知道,在X ...
- Android SVG矢量资源的使用方法
VectorDrawable 与 SVG Android 5.0(Lollipop, API 21)后,新增了<vector>标签,以VectorDrawable的形式支持SVG类型矢量图 ...
- 模仿qq界面实现(WTL)
前面对于界面用哪一种我试过用duilib,但是老感觉和MFC差距有点多,终于发现WTL的库能够实现我的所有界面功能,几天的努力终于搞定界面的重写.还是见我的成果吧: 1登录界面: 2主界面: 3.主界 ...
- Javascript/js的相等和不等运算符(= 、== 、===)
"=="和"==="运算符用于比较两个值是否相等,当然它们对相等的定义不尽相同.两个运算符允许任意类型的操作数,如果操作数相等则返回tru,否则返回false. ...
- Javascript之深入浅出prototype
我们先来讲一个故事,一个大大的池塘,里面有很多鱼.这是属于我们大家的池塘所以里面的鱼我们都可以吃,但是我们也会从集市买一些鱼放在家里,那么放在家里的鱼肯定是属于我们私人的,外人是不会拥有的.那么在js ...
- bzoj3238--后缀自动机
显然只需求LCP(i,j)就可以了. 将s反转,然后插入后缀自动机.由于后缀自动机的link指针构成了一棵后缀树,而字符串又反转过,所以两个结点的LCP就是LCA. 树形DP,求出以每个结点为LCA的 ...
- Professional C# 6 and .NET Core 1.0 - Chapter 39 Windows Services
本文内容为转载,供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - Chapter 39 Windows Servi ...
- C语言的函数类型
C语言的函数类型与返回值类型不一致时出现,是以函数类型为标准; 而如果在java与c#语言中上述情况是编译错误的;
- JS验证电话号是否合法
/******************** 函数名称:IsTelephone 函数功能:固话,手机号码检查函数,合法返回true,反之,返回false 函数参数:obj,待检查的号码 检查规则: (1 ...
- ArcObjects与ArcEngine的联系与区别
ArcObjects与ArcEngine的联系与区别 AO一般指的是桌面产品开发组件,需要在桌面环境中才能够使用,最典型的就是嵌入式VBA开发.但是这样带来的弊端和OFFICE等相关软件一样明显,就是 ...