POJ1463 - Horizontally Visible Segments(区间覆盖)

题目大意

给出N条线段的x坐标,以及两个y坐标,要求你求出线段之间两两相互可见的三元组数量

题解

先对线段按x坐标升序排序,按顺序进行处理,每次先查询操作,如果当前线段i与其之前的某个线段可见,那么在它们之间建立一条边(用容器来存储),表示它们两相互可见,然后再进行更新操作。处理完之后就是统计了,直接暴力即可。。。还有就是容器记得初始化。。。我被坑了。。。

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<vector>

using namespace std;

#define MAXN 8005

#define lson l,m,s<<1

#define rson m+1,r,s<<1|1

typedef struct {

    int x;

    int y1;

    int y2;

} NODE;

NODE seg[MAXN];

int setv[MAXN<<3],hash[MAXN];

vector<int> g[MAXN];

bool cmp(NODE a,NODE b)

{

    return a.x<b.x;

}

void PushDown(int s)

{

    if(setv[s]) {

        setv[s<<1]=setv[s<<1|1]=setv[s];

        setv[s]=0;

    }

}

void update(int ql,int qr,int d,int l,int r,int s)

{

    if(ql<=l&&r<=qr) {

        setv[s]=d;

        return;

    }

    PushDown(s);

    int m=(l+r)>>1;

    if(ql<=m) update(ql,qr,d,lson);

    if(qr>m) update(ql,qr,d,rson);

}

void query(int ql,int qr,int d,int l,int r,int s)

{

    if(setv[s]) {

        if(hash[setv[s]]!=d) {

            g[d].push_back(setv[s]);

            hash[setv[s]]=d;

        }

        return;

    }

    if(l==r) return;

    PushDown(s);

    int m=(l+r)>>1;

    if(ql<=m) query(ql,qr,d,lson);

    if(qr>m) query(ql,qr,d,rson);



}

int main(void)

{

    int T,n;

    scanf("%d",&T);

    while(T--) {

        int y1,y2;

        scanf("%d",&n);

        for(int i=1; i<=n; i++) {

            scanf("%d%d%d",&y1,&y2,&seg[i].x);

            seg[i].y1=y1*2;

            seg[i].y2=y2*2;

            g[i].clear();

        }

        memset(setv,0,sizeof(setv));

        memset(hash,0,sizeof(hash));

        sort(seg+1,seg+n+1,cmp);

        for(int i=1; i<=n; i++) {

            query(seg[i].y1,seg[i].y2,i,0,MAXN<<1,1);

            update(seg[i].y1,seg[i].y2,i,0,MAXN<<1,1);

        }

        int ans=0,a,b,t,temp,c;

        for(int i=1; i<=n; i++) {

            t=g[i].size();

            for(int j=0; j<t-1; j++)

                for(int k=j+1; k<t; k++) {

                    a=g[i][j];

                    b=g[i][k];

                    if(a<b) {

                        temp=a;

                        a=b;

                        b=temp;

                    }

                    c=g[a].size();

                    for(int p=0; p<c; p++)

                        if(g[a][p]==b) {

                            ans++;

                            break;

                        }

                }

        }

        printf("%d\n",ans);

    }

    return 0;

}

你可能感兴趣的:(visible)