Horizontally Visible Segments
Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 3701 | Accepted: 1360 |
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.
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.
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 题意:x轴上有很多垂直的线段,两个线段之间的连线和其他的线段没有交点叫可见,给出一组数据,叫你求选出3跳线段,然后这三条线段两两可见的,求出满足这个条件的 三条线段的组数。 分析:将输入的的线段按x从小到大排列,然后先查询再更新,就是每次插入线段之前,先查询即将插入的那条线段和以前插入的线段是否可见,因为线段一旦插入就可能覆盖 了之前插入且和插入的这条线段可见的线段,每条线段都有一种颜色,所以我们可以用一个vis数组来存储哪些颜色可见,到最后直接暴力枚举就可以过了(容易MLE)。#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=16100; bool vis[MAXN>>1][MAXN>>1]; struct seg { int l,r; int color; }tree[MAXN<<2]; struct Node { int x,y1,y2; }p[MAXN>>1]; bool cmp(Node a,Node b) { return a.x<b.x; } void build(int l,int r,int k) { tree[k].l=l; tree[k].r=r; tree[k].color=0; if(l==r) return; int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); } void pushdown(int k) { tree[k<<1].color=tree[k<<1|1].color=tree[k].color; tree[k].color=-1; } void query(int l,int r,int k,int val) { if(tree[k].color!=-1) { vis[tree[k].color][val]=1; return; } if(tree[k].l==tree[k].r) return; if(tree[k].color!=-1) pushdown(k); int mid=(tree[k].l+tree[k].r)>>1; if(l<=tree[k<<1].r) query(l,r,k<<1,val); if(r>=tree[k<<1|1].l) query(l,r,k<<1|1,val); } void update(int l,int r,int k,int val) { if(tree[k].l>=l&&tree[k].r<=r) { tree[k].color=val; return; } if(tree[k].color!=-1) pushdown(k); if(l<=tree[k<<1].r) update(l,r,k<<1,val); if(r>=tree[k<<1|1].l) update(l,r,k<<1|1,val); } int main() { int t,n,i,j,k; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d%d",&p[i].y1,&p[i].y2,&p[i].x); p[i].y1=2*p[i].y1; p[i].y2=2*p[i].y2; } build(0,MAXN,1); sort(p+1,p+n+1,cmp); memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) { query(p[i].y1,p[i].y2,1,i); update(p[i].y1,p[i].y2,1,i); } int ans=0; for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(vis[i][j]) for(k=1;k<=n;k++) { if(vis[i][k]&&vis[j][k]) ans++; } printf("%d\n",ans); } return 0; }