题意:

有一些平行于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*4];
vector<int>e[N];
void build(int l,int r,int i)
{
    id[i]=0;
    if(l!=r)
    {
        int mid=(l+r)>>1;
        build(l,mid,i<<1);
        build(mid+1,r,i<<1|1);
    }
}
void pushdown(int i)
{
    if(id[i]!=-1)
    {
        id[i<<1]=id[i<<1|1]=id[i];
        id[i]=-1;
    }
}
void update(int l,int r,int pl,int pr,int va,int i)
{
    if(l>=pl&&r<=pr)
    {
        if(id[i]!=-1)
        {
            e[id[i]].push_back(va);
            id[i]=va;
            return;
        }
        id[i]=va;
    }
    if(id[i]!=va)
        pushdown(i);
    int mid=(l+r)>>1;
    if(pl<=mid)update(l,mid,pl,pr,va,i<<1);
    if(pr>mid)update(mid+1,r,pl,pr,va,i<<1|1);
}
struct node
{
    int y1,y2,x;
}s[16000];
bool cmp(node a,node b)
{
    return a.x<b.x;
}
int cas[N];
int main() {
    int tt,n,ri=0;
    memset(cas,0,sizeof(cas));
    scanf("%d",&tt);
    while(tt--)
    {
        int maxn=17000;
        build(1,maxn,1);
        scanf("%d",&n);
        for(int i=1;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*2-1;
            s[i].y2=s[i].y2*2-1;
        }
        sort(s+1,s+n+1,cmp);
        for(int i=0;i<=n;++i)e[i].clear();
        for(int i=1;i<=n;++i)
        {
            int l,r;
            l=s[i].y1;
            r=s[i].y2;
            update(1,maxn,l,r,i,1);
        }
        for(int i=1;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=0;
        for(int i=1;i<=n;++i)
        {
            ri++;
            for(int j=0;j<e[i].size();++j)
                cas[e[i][j]]=ri;
            for(int j=0;j<e[i].size();++j)
            {
                int now=e[i][j];
                for(int k=0;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 0;
}

 

posted on 2014-07-30 23:49  L_Ecry  阅读(187)  评论(0编辑  收藏  举报