poj 3277 线段树求区间并1

所有矩形有相同的下边界,求 并 的面积


#include <stdio.h>
#include <algorithm>

using namespace std;
#define N 80001
#define L(i) i<<1
#define R(i) i<<1|1
struct City
{
    __int64 l,r,h;
    void input()
    {
        scanf("%I64d%I64d%I64d",&l,&r,&h);
    }
}building[N];
struct node{
    int l,r;
    __int64 h;
    int mid()
    {
        return (l + r)>>1;
    }
}st[N<<2];

bool cmp(City a,City b)
{
    return a.h < b.h;
}
int n,top;
__int64 hash[N];
__int64 sum;

int bs(__int64 s)
{
    int mid,l = 0, r = top -1;
    while(l <= r)
    {
        mid = (l + r)>>1;
        if(hash[mid] == s)
            return mid;
        if(hash[mid] < s)
            l = mid + 1;
        else
            r = mid - 1;
    }
    return -1;
}
void build(int l,int r,int id)
{
    st[id].l = l;
    st[id].r = r;
    st[id].h = 0;
    if(l + 1 != r)///叶子结点
    {
        int mid = st[id].mid();
        build(l,mid,L(id));
        build(mid,r,R(id));
    }
}
void insert(int l,int r,__int64 h,int id)
{
    if(st[id].l == l && st[id].r == r)
    {
        st[id].h = h;
        return ;
    }
    if(st[id].h)
    {
        st[L(id)].h = st[R(id)].h = st[id].h;
        st[id].h = 0;
    }
    int mid = st[id].mid();
    if(mid >= r)
        insert(l,r,h,L(id));
    else if(mid <= l)
        insert(l,r,h,R(id));
    else
    {
        insert(l,mid,h,L(id));
        insert(mid,r,h,R(id));
    }
}
void query(int id)
{
    if(st[id].h)
    {
        sum += st[id].h * (hash[st[id].r] - hash[st[id].l]);
        return ;
    }

    if(st[id].l + 1 == st[id].r)
        return ;
    query(L(id));
    query(R(id));
}
int main()
{
    scanf("%d",&n);
    top = 0;
    int i;
    for(i = 0; i < n ; ++i)
    {
        building[i].input();
        hash[top++] = building[i].l;
        hash[top++] = building[i].r;
    }
    sort(hash,hash+top);
    sort(building,building + n, cmp);
    int m = top;
    top = 1;
    for(i = 1;i < m; ++i)///离散化
        if(hash[i] != hash[i-1])
            hash[top++] = hash[i];

    build(0,top - 1,1);

    for(i = 0;i < n; ++i)
    {
        int a = bs(building[i].l),b = bs(building[i].r);
        insert( a, b,building[i].h,1);
    }
    sum = 0;
    query(1);
    printf("%I64d\n",sum);
    return 0;
}
/*

4
2 5 1
9 10 4
6 8 2
4 6 3

16
*/


你可能感兴趣的:(poj 3277 线段树求区间并1)