线段树 poj 1436

题目大意:给出n条垂直于x轴的线段的数据y1,y2,x,求出有几个三条线段一组的三元组并且他们兩兩能相见的。
思路:对y轴建树,将x排序,然后按顺序边询问边擦入,用mark[i][j]表示j往左可以看到i。最后用一个三重循环计算答案。
但是注意:0,4,1 和 0,2,2 和 3,4,2这三条线段覆盖的结果是区间0~4通过线段树查找可见线段是两条,其实是3条(2~3可见另一条)
这里可以将y轴×2表示。这样就能解决这样的问题
0 1 2 3 4 2~3被覆盖 所以乘2解决
#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\n",ans);
    }
    return 0;
}

 

 

posted on 2016-12-20 17:02  HelloWorld!--By-MJY  阅读(110)  评论(0编辑  收藏  举报

导航