题目大意:给出n条垂直于x轴的线段的数据y1,y2,x,求出有几个三条线段一组的三元组并且他们兩兩能相见的。
思路:对y轴建树,将x排序,然后按顺序边询问边擦入,用mark[i][j]表示j往左可以看到i。最后用一个三重循环计算答案。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAXN 16005
struct node
{
int l,r,w;
}x[MAXN<<3];
struct abc
{
int y1,y2,x;
}z[MAXN];
bool m1[MAXN/2][MAXN/2];
bool cmp(abc a,abc b)
{
return a.x<b.x;
}
void push_down(int a)
{
x[a<<1].w=x[a<<1|1].w=x[a].w;
x[a].w=-1;
}
void Build(int l,int r,int a)
{
x[a].l=l;
x[a].r=r;
x[a].w=-1;
if(l==r)
return ;
int mid=(l+r)>>1;
Build(l,mid,a<<1);
Build(mid+1,r,a<<1|1);
}
void Insert(int l,int r,int i,int a)
{
if(z[i].y1<=l&&r<=z[i].y2)
{
x[a].w=i;
return ;
}
if(l==r)
return ;
if(x[a].w!=-1)
push_down(a);
int mid=(l+r)>>1;
if(z[i].y1<=mid)
Insert(l,mid,i,a<<1);
if(z[i].y2>mid)
Insert(mid+1,r,i,a<<1|1);
}
void Ques(int l,int r,int i,int a)
{
if(x[a].w!=-1)
{
m1[x[a].w][i]=1;
return ;
}
if(l==r)
return ;
if(x[a].w!=-1)
push_down(a);
int mid=(l+r)>>1;
if(z[i].y1<=mid)
Ques(l,mid,i,a<<1);
if(z[i].y2>mid)
Ques(mid+1,r,i,a<<1|1);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
memset(m1,0,sizeof(m1));
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&z[i].y1,&z[i].y2,&z[i].x);
z[i].y1<<=1;
z[i].y2<<=1;
}
Build(0,MAXN,1);
sort(z+1,z+n+1,cmp);
for(int i=1;i<=n;i++)
{
Ques(0,MAXN,i,1);
Insert(0,MAXN,i,1);
}
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(m1[i][j])
for(int k=1;k<=n;k++)
if(m1[i][k]&&m1[j][k])
ans++;
printf("%d
",ans);
}
return 0;
}