Horizontally Visible Segments POJ - 1436 (segment tree interval coverage)

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?

Task

Write a program which for each data set:

reads the description of a set of vertical segments,

computes the number of triangles in this set,

writes the result.
Input
The first line of the input contains exactly one positive integer d equal to the number of data sets, 1 <= d <= 20. The data sets follow.

The first line of each data set contains exactly one integer n, 1 <= n <= 8 000, equal to the number of vertical line segments.

Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:

yi’, yi’’, xi - y-coordinate of the beginning of a segment, y-coordinate of its end and its x-coordinate, respectively. The coordinates satisfy 0 <= yi’ < yi’’ <= 8 000, 0 <= xi <= 8 000. The segments are disjoint.
Output
The output should consist of exactly d lines, one line for each data set. Line i should contain exactly one integer equal to the number of triangles in the i-th data set.
Sample Input
1
5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
Sample Output
1

Meaning of the title:
the n-bar vertical line, horizontal line if there is not a straight line through the other, it is called visible. Three straight lines with each other become visible "triangle." How much demand "triangle"
ideas:
ideas tree line interval coverage of good writing, but the key is the back three for the enumeration, if it reaches the n- 3 square complexity, for n≤8000 is unacceptable.
However, a total of 8000 points, y largest and 8000.
For the first segment, is to make all other segments "see", in order to satisfy the rest of the points to be filled.

So if the second line segment length len is filled, then the second segment can only be seen len line segments, the first segment is seen to reduce the number len.

Thus readily available at most 8000k (k is a small constant) for each visible.

So the complexity of the actual n- 2 logN, for the (1,2), (3,4), (2,3), (2,3) may be masked as a closed interval, so that each point is multiplied by 2, point extended range segment range.

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 8000 * 2 + 2;
bool maze[maxn / 2][maxn / 2];//开成int类型会mle

struct Node
{
    int l,r;
    int cover;
}t[maxn << 2];

struct Point
{
    int x,y1,y2;
}p[maxn / 2];

int cmp(Point a,Point b)
{
    return a.x < b.x;
}

void pushup(int i)
{
    if(t[i * 2].cover == -1 || t[i * 2 + 1].cover == -1)t[i].cover = -1;
    else if(t[i * 2].cover != t[i * 2 + 1].cover)t[i].cover = -1;
    else t[i].cover = t[i * 2].cover;
}

void pushdown(int i)
{
    if(t[i].cover != -1)
    {
        t[i * 2].cover = t[i * 2 + 1].cover = t[i].cover;
    }
}

void build(int i,int l,int r)
{
    t[i].l = l;t[i].r = r;
    t[i].cover = 0;
    if(l == r)return;
    int m = (l + r) >> 1;
    build(i * 2,l,m);
    build(i * 2 + 1, m + 1,r);
    pushup(i);
}

void update(int i,int x,int y,int v)
{
    if(x <= t[i].l && t[i].r <= y)
    {
        t[i].cover = v;
        return;
    }
    pushdown(i);
    int m = (t[i].l + t[i].r) >> 1;
    if(x <= m)update(i * 2,x,y,v);
    if(y > m)update(i * 2 + 1,x,y,v);
    pushup(i);
}

void query(int i,int x,int y,int v)
{
    if(t[i].cover != -1)
    {
        maze[t[i].cover][v] = maze[v][t[i].cover] = 1;
        return;
    }
    int m = (t[i].l + t[i].r) >> 1;
    if(x <= m)query(i * 2,x,y,v);
    if(y > m)query(i * 2 + 1,x,y,v);
}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n;scanf("%d",&n);
        for(int i = 1;i <= n;i++)
        {
            scanf("%d%d%d",&p[i].y1,&p[i].y2,&p[i].x);
            p[i].y1 *= 2;p[i].y2 *= 2;
        }
        sort(p + 1,p + 1 + n,cmp);
        memset(maze,0,sizeof(maze));
        build(1,0,maxn);
        for(int i = 1;i <= n;i++)
        {
            query(1,p[i].y1,p[i].y2,i);
            update(1,p[i].y1,p[i].y2,i);
        }
        
        int ans = 0;
        for(int i = 1;i <= n;i++)
        {
            for(int j = i + 1;j <= n;j++)
            {
                if(maze[i][j])
                {
                    for(int k = j + 1;k <= n;k++)
                    {
                        if(maze[i][k] && maze[j][k])
                        {
                            ans++;
                        }
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

Published 628 original articles · won praise 17 · views 20000 +

Guess you like

Origin blog.csdn.net/tomjobs/article/details/104076276