(中等) POJ 1436 Horizontally Visible Segments , 线段树+区间更新。

Description

  There is a number of disjoint vertical line segments in the plane. We say that two segments are horizontally visible if they can be connected by a horizontal line segment that does not have any common points with other vertical segments. Three different vertical segments are said to form a triangle of segments if each two of them are horizontally visible. How many triangles can be found in a given set of vertical segments?

  题意大致就是说给你一些线段,问相邻两个线段有没有公共的部分,且没有其他线段阻挡。

  

  首先对x排序,然后枚举,对于每个线段,先询问这个区间上的所有其他线段,然后再覆盖更新。

  对于COL数组,如果为-1表示这个区间上有多个线段,否则的话表示的是线段的编号(这里假设先放了一个编号为0的线段。)

  (PS:我能说这个题我调试了一下午吗,刚开始把COL设置为了bool的变量,结果。。。T T , 一直没找出错误来。。。痛苦。。。)

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>

#define lson L,M,po*2
#define rson M+1,R,po*2+1

using namespace std;

const int N=8000*2;

int COL[8008*2*4];
bool map1[8008][8008];

void pushDown(int po)
{
    if(COL[po]>=0)
    {
        COL[po*2]=COL[po*2+1]=COL[po];
        COL[po]=-1;
    }
}

void update(int ul,int ur,int ut,int L,int R,int po)
{
    if(ul<=L&&ur>=R)
    {
        COL[po]=ut;

        return;
    }

    pushDown(po);

    int M=(L+R)/2;

    if(ul<=M)
        update(ul,ur,ut,lson);
    if(ur>M)
        update(ul,ur,ut,rson);

    if(COL[po*2]==COL[po*2+1])          //这里算是一个剪枝操作,可以减少递归次数。
        COL[po]=COL[po*2];
    else
        COL[po]=-1;
}

void query(int ql,int qr,int qt,int L,int R,int po)
{
    if(COL[po]!=-1)
    {
        map1[qt][COL[po]]=map1[COL[po]][qt]=1;
        return;
    }

    if(L==R)
        return;

    int M=(L+R)/2;

    if(ql<=M)
        query(ql,qr,qt,lson);
    if(qr>M)
        query(ql,qr,qt,rson);
}

struct state
{
    int y1,y2,x1;
};

state sta[8008];

int cmp(const void*a,const void*b)
{
    return (*(state*)a).x1-(*(state*)b).x1;
}

int main()
{
    int d;
    cin>>d;

    int n;

    while(d--)
    {
        memset(map1,0,sizeof(map1));
        memset(COL,0,sizeof(COL));

        cin>>n;

        for(int i=0;i<n;++i)
            scanf("%d %d %d",&sta[i].y1,&sta[i].y2,&sta[i].x1);

        qsort(sta,n,sizeof(state),cmp);

        for(int i=1;i<=n;++i)
        {
            query(sta[i-1].y1*2,sta[i-1].y2*2,i,0,N,1);
            update(sta[i-1].y1*2,sta[i-1].y2*2,i,0,N,1);
        }

        long long ans=0;

        for(int i=1;i<=n;++i)           //直接暴力求解,居然不超时。。。
            for(int j=i+1;j<=n;++j)
                if(map1[i][j])
                    for(int k=j+1;k<=n;++k)
                        if(map1[i][k]&&map1[j][k])
                            ++ans;

        cout<<ans<<endl;
    }

    return 0;
}

时间: 2024-11-08 19:02:08

(中等) POJ 1436 Horizontally Visible Segments , 线段树+区间更新。的相关文章

POJ 1436 Horizontally Visible Segments (线段树&amp;#183;区间染色)

题意   在坐标系中有n条平行于y轴的线段  当一条线段与还有一条线段之间能够连一条平行与x轴的线不与其他线段相交  就视为它们是可见的  问有多少组三条线段两两相互可见 先把全部线段存下来  并按x坐标排序  线段树记录相应区间从右往左当前可见的线段编号(1...n)  超过一条就为0  然后从左往右对每条线段  先查询左边哪些线段和它是可见的  把可见关系存到数组中  然后把这条线段相应区间的最右端可见编号更新为这条线段的编号  最后暴力统计有多少组即可了 #include <cstdio>

POJ 1436 Horizontally Visible Segments(线段树)

POJ 1436 Horizontally Visible Segments 题目链接 线段树处理染色问题,把线段排序,从左往右扫描处理出每个线段能看到的右边的线段,然后利用bitset维护枚举两个线段,找出另一个两个都有的线段 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <bitset> #include <vector> using namesp

POJ 1436 Horizontally Visible Segments(线段树建图+枚举)

题目连接:http://poj.org/problem?id=1436 题意:给一些线段,每个线段有三个值y1, y2, x代表起点为(x, y1),终点为(x, y2)的线段.当从一个线段可以作水平线到另一个线段并且不穿过其他线段时,就称这两个线段时水平可见的.当三个线段可以两两水平可见,就称为形成一个线段三角.问:在这些线段中有多少个这样的线段三角? 分析:可以把每条线段看做是一个点,如果它和其他线段是水平可见的,就将这两个点相连,由于是无向图,就是你能看到我,我也能看到你,所以需要连接两次

POJ - 1436 Horizontally Visible Segments

Description There is a number of disjoint vertical line segments in the plane. We say that two segments are horizontally visible if they can be connected by a horizontal line segment that does not have any common points with other vertical segments.

poj 2528 Mayor&#39;s posters 线段树区间更新

Mayor's posters Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at al

POJ 2777 Count Color (线段树区间更新加查询)

Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. There is a very long board with length L centimeter, L is a positive integer, so we can evenly d

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

poj 2777 Count Color (线段树区间更新)

Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37647   Accepted: 11315 Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.

poj 1436 Horizontally Visible Segments(线段树、区间覆盖)

Horizontally Visible Segments Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4645   Accepted: 1706 Description There is a number of disjoint vertical line segments in the plane. We say that two segments are horizontally visible if they