题目大意:

在一个平面内,有一些竖直的线段,若两条竖直线段之间可以连一条水平线,这条水平线不与其他竖直线段相交,称这两条竖直线段为“相互可见”的。若存在三条竖直线段,两两“相互可见”,则构成“线段三角形”。给出一些竖直的线段,问一共有多少“线段三角形”。

首先处理端点问题:想象一下若同一x位置有两条线段,y坐标为1~2和3~4。其实中间的空当2~3之间是可以引水平线段的,而这里我们都用整数处理,那条水平线段就被忽略了,可能会导致有一些水平相互可见的线段在计算中被忽略了,这里我们扩大y坐标之间的空间,这时我们就可以多出一个整数来便于我们的整数处理,这样就可以简单地处理端点问题,并且它对于所有情况都有很好的效果.自己画个图就明白了。

线段处理:首先对线段以X大小进行排序;再进行询问,询问时是以当前的线段与先前的线段是不是“相互可见”的;再进行更新。

这里我们用到了覆盖的原则。如果不明白先做做这个题吧。http://poj.org/problem?id=2777

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<vector>using namespace std;class Node{public:int l ,r ,c;    };class segment{public:int y1,y2,x;    };Node tree[40024];int v[10024];segment seg[10024];vector<int>see[10024];class Tree{public:void Maketree( int l, int r ,int cnt );void Update( int l, int r ,int cnt, int id );void Query( int l ,int r, int cnt, int id );};void Tree::Maketree( int l ,int r, int cnt ){   tree[cnt].l = l;   tree[cnt].r = r;   tree[cnt].c = -1;//-1表示该区间有个线段;    if( l == r ) return ;int mid = ( l + r )>>1;   Maketree( l , mid , cnt*2 );   Maketree( mid + 1 ,r ,cnt*2+1 );    }void Tree::Update( int l ,int r, int cnt , int id ){if( l <= tree[cnt].l&& r >= tree[cnt].r )//符合要求的区间被覆盖    {      tree[cnt].c = id;return;           } else   {if( tree[cnt].c != -1 )//如果不为-1则表示该区间(y轴这个区间)只有一条线段那么就要复原       {         tree[cnt*2].c = tree[cnt*2+1].c = tree[cnt].c;         tree[cnt].c = -1;              }int mid = ( tree[cnt].l + tree[cnt].r )>>1;if( r > mid )             Update( l , r , cnt*2 +1 , id );if( l <= mid )            Update( l , r , cnt*2  , id );if( tree[cnt*2].c == tree[cnt*2+1].c )//由下往上更新          tree[cnt].c = tree[cnt*2].c;else tree[cnt].c = -1;           }}void Tree::Query(int l, int r ,int cnt , int id){//    if( l > tree[cnt].r || r > tree[cnt].l )//        return ;    if( tree[cnt].c != -1 )    {if( v[tree[cnt].c] != id )       {           see[ tree[cnt].c ].push_back( id );           v[tree[cnt].c] = id;                }return ;        }//    Query( l , r, cnt*2 + 1, id );//    Query( l , r , cnt *2 ,id );    if( tree[cnt].l == tree[cnt].r ) return;else    {int mid = ( tree[cnt].l + tree[cnt].r )>>1;if( mid < l )            Query( l , r, cnt*2 + 1, id );else        {if( r <= mid )             Query( l , r, cnt*2 , id );else         {             Query( l , mid , cnt *2 ,id );             Query( mid + 1 , r ,cnt*2+1 , id );                 }          }       }}bool cmp( segment a ,segment b ){return a.x < b.x;    }int main( ){int n,m;while( scanf( "%d",&n )==1 )   {while( n-- )       {          Tree e;          scanf( "%d",&m );for( int i=0; i<m ;i++ )          {             scanf( "%d%d%d",&seg[i].y1, &seg[i].y2 ,&seg[i].x );             seg[i].y1 *= 2;             seg[i].y2 *= 2;             see[i].clear();                  }                  e.Maketree( 0 , 16000 , 1 );          sort( seg , seg+m ,cmp );           memset( v , -1 ,sizeof( v ) );for( int i = 0 ; i< m ;i++ )          {              e.Query( seg[i].y1, seg[i].y2 , 1 , i );              e.Update( seg[i].y1 , seg[i]. y2 , 1 ,i );                   }int ans = 0;for( int i= 0 ; i < m ;i++ )          {int t = see[i].size();for( int j= 0 ; j< t ;j++ )             {for( int k = j+1 ;k< t ;k++ )                 {int z = see[see[i][j]].size();for( int l = 0 ; l < z ; l++ )                     {if( see[i][k] == see[see[i][j]][l] )                        {                           ans++;break;                        }                     }                         }                     }                  }          printf( "%d\n",ans );       }           }return 0;    }

转载于:https://www.cnblogs.com/bo-tao/archive/2012/02/27/2370276.html

poj 1436 Horizontally Visible Segments相关推荐

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

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

  2. 线段树开新坑:kuangbin带你飞

    写在最前面的废话 这里I以前的题是暑假刚刚开始的时候在家写的,然后多校一波就荒废了 9月开头回家一波,重新填坑,= =,kuangbin带你飞的pdf,这才一半题,后面还有一波,蓝瘦,慢慢写吧,不写题 ...

  3. POJ前面的题目算法思路【转】

    1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 85% 2005-5-7 1002 487-3279 n/a 90% 2005-5- ...

  4. POJ 超详细分类

    POJ 各题算法 1000    A+B Problem            送分题     49%    2005-5-7 1001    Exponentiation         高精度   ...

  5. 数据结构---线段树

    线段树 转载请注明出处,谢谢!http://blog.csdn.net/metalseed/article/details/8039326  持续更新中···   一:线段树基本概念 1:概述 线段树 ...

  6. 【转】线段树题目 汇总 讲解(by not only success)

    转载自:http://www.notonlysuccess.com/ 非常喜欢他的代码风格以及简洁的思路,感谢notonlysuccess! PS:他的个人网站好像是上不去了-.- 线段树 很早前写的 ...

  7. ACM大牛总结的线段树专辑

    https://blog.csdn.net/qq_25605637/article/details/46967529 [完全版]线段树 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章 ...

  8. 【转载】完全版线段树 by notonlysuccess大牛

    原文出处:http://www.notonlysuccess.com/ 今晚上比赛就考到了 排兵布阵啊,难受. [完全版]线段树 很早前写的那篇线段树专辑至今一直是本博客阅读点击量最大的一片文章,当时 ...

  9. 转载自杭电大牛的博客 线段树 绝对经典

    转载自:http://www.notonlysuccess.com/ 不可不看的经典 学线段树必看,大牛很多,给后人留下记录的却没有几个,谢谢这位大牛~! 因为我这最近他博客打不开了...特意从别人那 ...

最新文章

  1. C++/C++11中std::priority_queue的使用
  2. Leangoo新功能-卡片ID
  3. Xtragrd 取消当前行
  4. 腾讯招.NET,居然要求精通MySQL,而不是SQLServer!
  5. 产品管理:启示录 - 特约客户、产品验证、原型测试
  6. cuda矩阵相乘_cuda初学(1):稀疏矩阵向量乘法(单精度)
  7. 标量、向量、矩阵、张量
  8. 解决正在等待响应_解决一些等待问题
  9. sqlserver使用depart获取当前日期月份及通过拼接得到日期时间
  10. Matlab中使用varargin来实现参数可变的函数
  11. linux上openmp测试
  12. 合并两个有序数组的三种方法
  13. 工厂模式(Factory Method)
  14. 4G+5G多卡聚合路由设备解决户外直播网络需求
  15. python自动做表格_用Python做自动化的表格处理(批量智能替换) - Python趣用之法2...
  16. [PyQt5]基本控件24 - 时间日期编辑框QDateTimeEdit
  17. 记账后,如何查看、修改或删除不需要的收支
  18. 轻松在Google Chrome浏览器中管理您的电子邮件
  19. 【Android 12.0】Android S WiFi启动业务流程分析(UML图)
  20. 网络编程学习(9)/ FTP项目(3) ——目录切换、目录查看功能

热门文章

  1. 长方形与圆最近连线LISP_餐桌到底选方还是圆?可千万别买错了,今天我们好好聊聊...
  2. SpringMVC对日期类型的转换
  3. DTC跨境电商白皮书
  4. eclipse一套全部流程的安装及配置
  5. 消息长度_【消息】听说咱安阳的第一条封闭外环即将全线通车了?是的,长度相当于北京五环...
  6. java、c语言、python、c++的不同之处_总结几点C/C++、Java与Python的区别
  7. 疲劳驾驶样本集_谷歌AI最新3D数据集,1.5万张动图,让AR主宰你的生活
  8. 基于分层注意力网络的方面情感分析
  9. 【计算机组成原理】I/O系统
  10. 【计算机科学基础】VonNeumann体系结构