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;
}

posted on 2013-05-22 08:32  仗剑奔走天涯  阅读(204)  评论(0编辑  收藏  举报

导航