首页 > 代码库 > POJ 1436 Horizontally Visible Segments

POJ 1436 Horizontally Visible Segments

题意:

有一些平行于y轴的线段 ,两条线段称为互相可见当且仅当存在一条水平线段连接这两条  与其他线段没交点。 最后问有多少组  3条线段,他们两两是可见的。

思路:

线段树,找出两两可见的那些组合,最后暴力判断。

#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<iostream>#include<vector>#define debug(x) printf(#x"= %d \n",x);#define N 20000using 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;}