zoukankan      html  css  js  c++  java
  • 线段树 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
    ",ans);
        }
        return 0;
    }
     
  • 相关阅读:
    金融系列7《动态数据认证》
    PHP异常处理详解
    C语言中的宏定义
    PHP SOCKET编程
    yii实现级联下拉菜单
    AR的一些常见的操作
    IP地址的三种表示格式及在Socket编程中的应用
    时间管理
    socket阻塞与非阻塞,同步与异步、I/O模型
    程序人生 PHP工程师
  • 原文地址:https://www.cnblogs.com/cherryMJY/p/6203342.html
Copyright © 2011-2022 走看看