题意:
有一些平行于y轴的线段 ,两条线段称为互相可见当且仅当存在一条水平线段连接这两条 与其他线段没交点。 最后问有多少组 3条线段,他们两两是可见的。
思路:
线段树,找出两两可见的那些组合,最后暴力判断。
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<vector>
#define debug(x) printf(#x"= %d \n",x);
#define N 20000
using namespace std;
int id[N*];
vector<int>e[N];
void build(int l,int r,int i)
{
id[i]=;
if(l!=r)
{
int mid=(l+r)>>;
build(l,mid,i<<);
build(mid+,r,i<<|);
}
}
void pushdown(int i)
{
if(id[i]!=-)
{
id[i<<]=id[i<<|]=id[i];
id[i]=-;
}
}
void update(int l,int r,int pl,int pr,int va,int i)
{
if(l>=pl&&r<=pr)
{
if(id[i]!=-)
{
e[id[i]].push_back(va);
id[i]=va;
return;
}
id[i]=va;
}
if(id[i]!=va)
pushdown(i);
int mid=(l+r)>>;
if(pl<=mid)update(l,mid,pl,pr,va,i<<);
if(pr>mid)update(mid+,r,pl,pr,va,i<<|);
}
struct node
{
int y1,y2,x;
}s[];
bool cmp(node a,node b)
{
return a.x<b.x;
}
int cas[N];
int main() {
int tt,n,ri=;
memset(cas,,sizeof(cas));
scanf("%d",&tt);
while(tt--)
{
int maxn=;
build(,maxn,);
scanf("%d",&n);
for(int i=;i<=n;++i)
{
scanf("%d%d%d",&s[i].y1,&s[i].y2,&s[i].x);
s[i].y1++;
s[i].y2++;
s[i].y1=s[i].y1*-;
s[i].y2=s[i].y2*-;
}
sort(s+,s+n+,cmp);
for(int i=;i<=n;++i)e[i].clear();
for(int i=;i<=n;++i)
{
int l,r;
l=s[i].y1;
r=s[i].y2;
update(,maxn,l,r,i,);
}
for(int i=;i<=n;++i)
{
sort(e[i].begin(),e[i].end());
e[i].erase(unique(e[i].begin(),e[i].end()),e[i].end());//去重
}
int ans=;
for(int i=;i<=n;++i)
{
ri++;
for(int j=;j<e[i].size();++j)
cas[e[i][j]]=ri;
for(int j=;j<e[i].size();++j)
{
int now=e[i][j];
for(int k=;k<e[now].size();++k)
{
if(cas[e[now][k]]==ri)
{
// printf("%d %d %d\n",i,now,e[now][k]);
ans++;
}
}
}
}
printf("%d\n",ans);
}
return ;
}