poj1436 Horizontally Visible Segments(区间覆盖+暴力)

借鉴这里:http://www.cnblogs.com/wuyiqi/archive/2012/02/02/2336350.html

有一些垂直于X轴的线段,两条线段能互相‘看见’的条件是,两条线段能由一条水平线连接,且这条水平线不能跟其他的所有线段有交点。 问3个线段能互相看见,这个条件下有多少组不同的。

先按x坐标进行排序,然后从左到右,一次对每条线段,先进行查询,看左边能看见多少条线段,然后进行覆盖,因为很明显,如果一条线段能看见另一条线段,那么这个关系必然是相互的,所以对每条线段,只需要往左看就行了,将能看见的线段编号都存入vector中,开一个used数组进行判重。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define havemid int m=(l+r)>>1
#define left (rt<<1)
#define right (rt<<1|1)
#define LL long long
const int maxn= 20000;
int cover[maxn<<3];
int used[maxn<<3];
vector<int>v[maxn];
void pushdown(int rt){
    if(cover[rt]!=-1){
        cover[left]=cover[right]=cover[rt];
        cover[rt]=-1;
    }
}
void update(int L,int R,int id,int l,int r,int rt){
    if(L<=l&&r<=R){
        cover[rt]=id;
        return ;
    }
    pushdown(rt);
    havemid;
    if(L<=m)update(L,R,id,lson);
    if(R>m)update(L,R,id,rson);
}
void query(int L,int R,int id,int l,int r,int rt){
    if(cover[rt]!=-1){
        if(used[cover[rt]]!=id){
            v[cover[rt]].push_back(id);
            used[cover[rt]]=id;
        }
        return ;
    }
    if(l==r)return ;
    pushdown(rt);
    havemid;
    if(L<=m)query(L,R,id,lson);
    if(R>m)query(L,R,id,rson);
}
int T,n;
struct node {
    int y,y1,x;
}q[10000];
int cmp (node a,node b){
    return a.x<b.x;
}
int main(){
    int i,j,k,z,t;
    scanf("%d",&T);
    while(T--){
        memset(cover,-1,sizeof(cover));
        memset(used,-1,sizeof(used));
        scanf("%d",&n);
        for(i=0;i<n;i++){
            v[i].clear();
        }
        for(i=0;i<n;i++){
            scanf("%d%d%d",&q[i].y,&q[i].y1,&q[i].x);
            q[i].y=q[i].y*2;
            q[i].y1=q[i].y1*2;
        }
        sort(q,q+n,cmp);
        for(i=0;i<n;i++){
            query(q[i].y,q[i].y1,i,1,17000,1);
            update(q[i].y,q[i].y1,i,1,17000,1);
        }
        int res=0;
        for(i=0;i<n;i++)
        for(j=0;j<v[i].size();j++){
            t=v[i][j];
            for(k=0;k<v[i].size();k++)
                for(z=0;z<v[t].size();z++)
                if(v[i][k]==v[t][z])
                res++;
        }
        printf("%d\n",res);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值