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的更多相关文章

  1. POJ 1436 Horizontally Visible Segments (线段树&#183;区间染色)

    题意   在坐标系中有n条平行于y轴的线段  当一条线段与还有一条线段之间能够连一条平行与x轴的线不与其他线段相交  就视为它们是可见的  问有多少组三条线段两两相互可见 先把全部线段存下来  并按x ...

  2. POJ 1436 Horizontally Visible Segments(线段树)

    POJ 1436 Horizontally Visible Segments 题目链接 线段树处理染色问题,把线段排序.从左往右扫描处理出每一个线段能看到的右边的线段,然后利用bitset维护枚举两个 ...

  3. poj 1436 && zoj 1391 Horizontally Visible Segments (Segment Tree)

    ZOJ :: Problems :: Show Problem 1436 -- Horizontally Visible Segments 用线段树记录表面能被看见的线段的编号,然后覆盖的时候同时把能 ...

  4. (中等) POJ 1436 Horizontally Visible Segments , 线段树+区间更新。

    Description There is a number of disjoint vertical line segments in the plane. We say that two segme ...

  5. 【37%】【poj1436】Horizontally Visible Segments

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5200   Accepted: 1903 Description There ...

  6. POJ 1436 Horizontally Visible Segments

    题意: 有一些平行于y轴的线段 ,两条线段称为互相可见当且仅当存在一条水平线段连接这两条  与其他线段没交点. 最后问有多少组  3条线段,他们两两是可见的. 思路: 线段树,找出两两可见的那些组合, ...

  7. POJ 1436 (线段树 区间染色) Horizontally Visible Segments

    这道题做了快两天了.首先就是按照这些竖直线段的横坐标进行从左到右排序. 将线段的端点投影到y轴上,线段树所维护的信息就是y轴区间内被哪条线段所覆盖. 对于一条线段来说,先查询和它能相连的所有线段,并加 ...

  8. poj1436 Horizontally Visible Segments

    这是一个区间更新的题目,先将区间放大两倍,至于为什么要放大可以这样解释,按照从左到右有4个区间,y值是[1,5],[1,2],[3,4],[1,4]如果不放大的话,查询[1,4]区间和前面区间的”可见 ...

  9. POJ 1436.Horizontally Visible Segments-线段树(区间更新、端点放大2倍)

    水博客,水一水. Horizontally Visible Segments Time Limit: 5000MS   Memory Limit: 65536K Total Submissions:  ...

随机推荐

  1. origin添加error bar

    增加一列,然后set as Y Error,然后全部选中显示就行了.

  2. Extjs换肤+cookie皮肤记忆功能

    http://www.myext.cn/kaifa/a_102.html    Ext之家 <title>无标题页</title>    <link rel=" ...

  3. iOS 插件化开发汇总 Small框架

    应用插件化背景 目前很多应用功能越来越多,软件显得越来越臃肿.因此插件化就成了很多软件发展的必经之路,比如支付宝这种平台级别的软件: 页上密密麻麻的功能,而且还在增多,照这个趋势发展下去,软件包的大小 ...

  4. Intellij IDEA 建立文件夹目录问题

    问题: NEW一个package常出现文件夹层次问题 解决: 1.选中当前文件夹(要在该文件夹下添加): 2.右击此处: 3.添加即可. 链接:http://stackoverflow.com/que ...

  5. WinForm DataGridView控件、duck布局

    1.DataGridView控件 显示数据表 (1)后台数据绑定: List<xxx> list = new List<xxx>(); dataGridView1.DataSo ...

  6. java版二叉树算法实现

    import java.util.ArrayList; class BinaryTree { private static class TreeNode { int data; TreeNode le ...

  7. 初探Lambda表达式/Java多核编程【1】从集合到流

    从集合到流 接上一小节初探Lambda表达式/Java多核编程[0]从外部迭代到内部迭代,本小节将着手使用"流"这一概念进行"迭代"操作. 首先何为" ...

  8. Oracle DataGuard 升级 [11.2.0.1 -> 11.2.0.4]

    Oracle DataGuard 升级 [11.2.0.1 -> 11.2.0.4] Primary: 11.2.0.1 单机,Site A. Standby: 11.2.0.1 单机,Site ...

  9. mybatis入门-新手注意问题

    参数问题 在映射文件中通过parameterType指定输入参数的类型:在映射文件中通过resultType指定输出结果的类型. 占位符和拼接符问题 #{}表示一个占位符号,#{}接收输入参数,类型可 ...

  10. js-tab选项卡

    说道tab选项卡,顾名思义,就是切换不同内容分类,想必学过前端的都知道,tab有很多方法可以实现,最近刚跟师傅学了一种,感觉很简便,很实用哦.    一.先看一下结果 二.可以根据图来布局,首先上面标 ...