POJ 1436 区间染色

Horizontally Visible Segments
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 4507 Accepted: 1662

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

Source

 
 
题目意思:
给n条垂直x轴的线段,若两个线段之间存在没有其他线段挡着的地方,则称两个线段为可见的。若3条线段两两互为可见,称为一组,求n条线段中有多少组。
 
 
思路:
很明显线段树,按x坐标排序,以y建线段树,每加入一条边就和之前的颜色用visited标记起来,然后暴力三重循环即可(虽然一重循环是8000,但是实际上没这么多)。
注意,插入边的时候,边的两端点*2再插入,还是边界问题。
 
代码:
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <vector>
  6 #include <queue>
  7 #include <cmath>
  8 #include <set>
  9 using namespace std;
 10 
 11 #define N 10005
 12 #define ll root<<1
 13 #define rr root<<1|1
 14 #define mid (a[root].l+a[root].r)/2
 15 
 16 
 17 int max(int x,int y){return x>y?x:y;}
 18 int min(int x,int y){return x<y?x:y;}
 19 int abs(int x,int y){return x<0?-x:x;}
 20 
 21 struct Line{
 22     int y1, y2, x;
 23 }line[N];
 24 
 25 struct node{
 26     int l, r, val;
 27     bool f;
 28 }a[N*8];
 29 
 30 int n;
 31 bool visited[8002][8002];
 32 
 33 bool cmp(Line a,Line b){
 34     return a.x<b.x;
 35 }
 36 
 37 void build(int l,int r,int root){
 38     a[root].l=l;
 39     a[root].r=r;
 40     a[root].val=0;
 41     a[root].f=false;
 42     if(l==r) return;
 43     build(l,mid,ll);
 44     build(mid+1,r,rr);
 45 }
 46 
 47 void down(int root){
 48     if(a[root].f&&a[root].val>0&&a[root].l!=a[root].r){
 49         a[ll].val=a[rr].val=a[root].val;
 50         a[root].val=-1;
 51         a[ll].f=a[rr].f=true;
 52     }
 53 }
 54 void update(int l,int r,int val,int root){
 55     //if(!a[root].f) a[root].f=true;
 56     if(a[root].val==val) return;
 57     if(a[root].l==l&&a[root].r==r){
 58         if(!a[root].f){
 59             a[root].f=true;
 60             a[root].val=val;
 61             return;
 62         }
 63         else{
 64             if(a[root].val>0){
 65                 if(!visited[a[root].val][val]){
 66                     visited[a[root].val][val]=visited[val][a[root].val]=true;
 67                 }
 68                 a[root].val=val;
 69                 return;
 70             }
 71         }
 72     }
 73     down(root);
 74     if(r<=a[ll].r) update(l,r,val,ll);
 75     else if(l>=a[rr].l) update(l,r,val,rr);
 76     else{
 77         update(l,mid,val,ll);
 78         update(mid+1,r,val,rr);
 79     }
 80     if(a[ll].f||a[rr].f) a[root].f=true;
 81     if(a[ll].val==a[rr].val&&a[ll].val>0) a[root].val=a[ll].val;
 82 }
 83 
 84 void out(int root){
 85     if(a[root].l==a[root].r) {
 86         printf("%d ",a[root].val);return;
 87     }
 88     down(root);
 89     out(ll);
 90     out(rr);
 91 }
 92 main()
 93 {
 94     int t, i, j, k;
 95     cin>>t;
 96     while(t--){
 97         scanf("%d",&n);
 98         int minh=999999999, maxh=-1;
 99         for(i=0;i<n;i++){
100             scanf("%d %d %d",&line[i].y1,&line[i].y2,&line[i].x);
101             minh=min(min(line[i].y1,line[i].y2),minh);
102             maxh=max(max(line[i].y1,line[i].y2),maxh);
103         } 
104         build(minh*2,maxh*2,1);
105         sort(line,line+n,cmp);
106         memset(visited,false,sizeof(visited));
107         for(i=0;i<n;i++) update(line[i].y1*2,line[i].y2*2,i+1,1);//,out(1),cout<<endl;
108         int ans=0;
109         
110         for(i=1;i<=n;i++){
111             for(j=i+1;j<=n;j++){
112                 if(visited[i][j]){
113                     for(k=j+1;k<=n;k++){
114                         if(visited[j][k]&&visited[i][k]){
115                             ans++;
116                         }
117                     }
118                 }
119             }
120         }
121         printf("%d\n",ans);
122         
123     }
124 }

 

转载于:https://www.cnblogs.com/qq1012662902/p/4538267.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值