POJ1436: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?


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
 
题意:每条线段的x轴是固定的,还有就是线段的两个端点的y坐标,要求出三个线段两两可见的一共有几对
思路:为了方便处理,要将y坐标*2来处理
 
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int L = 8000+10;
int color[L<<3];
bool map[L][L];//一开始我存的int型,但是int型会超内存,用bool型能节省大量空间
int n;

struct node
{
    int l,r,n;
} a[L<<3];

struct kode
{
    int x,y1,y2;
} s[L];

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

void init(int l,int r,int i)
{
    a[i].l = l;
    a[i].r = r;
    a[i].n = 0;
    if(l==r)
        return;
    int mid = (l+r)>>1;
    init(l,mid,2*i);
    init(mid+1,r,2*i+1);
}

void insert(int l,int r,int i,int m)
{
    if(l<=a[i].l && a[i].r<=r)
    {
        a[i].n = m;
        return ;
    }
    if(a[i].n!=-1)//将父亲节点的状态更新到孩子节点中
    {
        a[2*i].n = a[2*i+1].n = a[i].n;
        a[i].n = -1;
    }
    if(l<=a[2*i].r)
        insert(l,r,2*i,m);
    if(r>=a[2*i+1].l)
        insert(l,r,2*i+1,m);
}

void query(int l,int r,int i,int m)
{
    if(a[i].n!=-1)
    {
        map[a[i].n][m] = true;
        return ;
    }
    if(a[i].l == a[i].r)
        return;
    if(a[i].n!=-1)
    {
        a[2*i].n = a[2*i+1].n = a[i].n;
        a[i].n = -1;
    }
    if(l<=a[2*i].r)
        query(l,r,2*i,m);
    if(r>=a[2*i+1].l)
        query(l,r,2*i+1,m);

}

int main()
{
    int t,ans,i,x,y1,y2,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i = 1; i<=n; i++)
        {
            scanf("%d%d%d",&s[i].y1,&s[i].y2,&s[i].x);
            s[i].y1*=2;
            s[i].y2*=2;;
        }
        sort(s+1,s+1+n,cmp);
        memset(map,false,sizeof(map));
        init(0,16000,1);
        for(i = 1; i<=n; i++)
        {
            query(s[i].y1,s[i].y2,1,i);
            insert(s[i].y1,s[i].y2,1,i);
        }
        ans = 0;
        for(i = 1; i<=n; i++)//暴力求解
            for(j = 1; j<=n; j++)
                if(map[i][j])
                {
                    for(k = 1; k<=n; k++)
                        if(map[i][k] && map[j][k])
                            ans++;
                }
        printf("%d\n",ans);
    }

    return 0;
}

你可能感兴趣的:(线段树,poj)