poj1436 Horizontally Visible Segments

Description

There is a number of disjoint vertical line segments in the plane. We say that two segments are horizontally visible if they can be connected by a horizontal line segment that does not have any common points with other vertical segments. Three different vertical segments are said to form a triangle of segments if each two of them are horizontally visible. How many triangles can be found in a given set of vertical segments? 


Task 

Write a program which for each data set: 

reads the description of a set of vertical segments, 

computes the number of triangles in this set, 

writes the result. 

Input

The first line of the input contains exactly one positive integer d equal to the number of data sets, 1 <= d <= 20. The data sets follow. 

The first line of each data set contains exactly one integer n, 1 <= n <= 8 000, equal to the number of vertical line segments. 

Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces: 

yi', yi'', xi - y-coordinate of the beginning of a segment, y-coordinate of its end and its x-coordinate, respectively. The coordinates satisfy 0 <= yi' < yi'' <= 8 000, 0 <= xi <= 8 000. The segments are disjoint.

Output

The output should consist of exactly d lines, one line for each data set. Line i should contain exactly one integer equal to the number of triangles in the i-th data set.

Sample Input

1
5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3

Sample Output

1

题目大意:给出n条垂直于x轴的线段的数据y1,y2,x,求出有几个三条线段一组的三元组并且他们兩兩能相见的。
思路:对y轴建树,将x排序,然后按顺序边询问边擦入,用mark[i][j]表示i往左可以看到j。最后用一个三重循环计算答案。
但是注意:0,4,1 和 0,2,2 和 3,4,2这三条线段覆盖的结果是区间0~4通过线段树查找可见线段是两条,其实是3条(2~3可见另一条)
这里可以将y轴×2表示。这样就能解决这样的问题
  1 /*
  2  * Author:  Joshua
  3  * Created Time:  2014年07月19日 星期六 15时26分20秒
  4  * File Name: poj1436.cpp
  5  */
  6 #include<cstdio>
  7 #include<cstring>
  8 #include<algorithm>
  9 using namespace std;
 10 
 11 #define maxn 8008
 12 #define L(x) (x <<1)
 13 #define R(x) (x << 1 |1)
 14 
 15 int T,maxv;
 16 bool mark[maxn][maxn];
 17 struct node
 18 {
 19     int l,r,color;
 20 } e[maxn << 4];
 21 struct edge
 22 {
 23     int y1,y2,x;
 24     edge(int Y1=0,int Y2=0,int X=0):y1(Y1),y2(Y2),x(X){}
 25     bool operator < (const edge &a) const 
 26     {
 27         return x<a.x;
 28     }
 29 } s[maxn];
 30 void build(int x,int l,int r)
 31 {
 32     e[x].color=0;
 33     e[x].l=l;
 34     e[x].r=r;
 35     if (l==r) return;
 36     int mid = l+r >>1;
 37     build(L(x),l,mid);
 38     build(R(x),mid+1,r);
 39 }
 40 void query(int x,int l,int r,int v)
 41 {
 42    if (e[x].color)
 43    {
 44        mark[v][e[x].color]=true;
 45        return;
 46    }
 47    int left=e[x].l,right=e[x].r;
 48    if (left==right) return;
 49    int mid = left+right >>1;
 50    if (l<=mid) query(L(x),l,r,v);
 51    if (r>mid) query(R(x),l,r,v);
 52 }
 53 
 54 void pushDown(int x)
 55 {
 56     if (e[x].color)
 57     {
 58         e[L(x)].color=e[R(x)].color=e[x].color;
 59         e[x].color=0;
 60     }
 61 }
 62 
 63 void updata(int x,int l,int r,int v)
 64 {
 65     int left=e[x].l,right=e[x].r;
 66     if (l<=left && right<=r)
 67     {
 68         e[x].color=v;
 69         return;
 70     }
 71     pushDown(x);
 72     int mid=left +right >>1;
 73     if (l<=mid) updata(L(x),l,r,v);
 74     if (r>mid) updata(R(x),l,r,v);
 75 }
 76    
 77 void solve()
 78 {
 79      int n,x,y1,y2;
 80      scanf("%d",&n);
 81      maxv=0;
 82      for (int i=1;i<=n;++i)
 83      {
 84          scanf("%d%d%d",&y1,&y2,&x);
 85          y1 <<=1;
 86          y2 <<=1;
 87          s[i]=edge(y1,y2,x);
 88          if (y2>maxv) maxv=y2;
 89      }
 90      build(1,0,maxv);
 91      sort(s+1,s+n+1);
 92      memset(mark,0,sizeof(mark));
 93      for (int i=1;i<=n;++i)
 94      {
 95          query(1,s[i].y1,s[i].y2,i);
 96          updata(1,s[i].y1,s[i].y2,i);
 97      }
 98      int ans=0;
 99      for (int i=1;i<=n;++i)
100          for (int j=i+1;j<=n;++j)
101              if (mark[j][i])
102                  for (int k=1;k<=i;++k)
103                      if (mark[i][k] && mark[j][k])
104                          ++ans;
105      printf("%d\n",ans);
106 }
107          
108 int main()
109 {
110     scanf("%d",&T);
111     while (T)
112     {
113         solve();
114         --T;
115     }
116 
117     return 0;
118 }

 

 

转载于:https://www.cnblogs.com/code-painter/p/3855643.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值