HDU 1542:线段树

题意:给N个矩形,会相互重叠,重叠部分只算一次面积,求总面积

把X坐标排序后离散化成0~m标号,每个标号代表一个点及其和下一个点之间的长度,所以m个点有m-1段。按0~m-1标号建线段树

上边赋值为-1,下边赋值为1,这样一段长度非零的时候,说明当前该段长度是被覆盖的,还需要被计算

这里比较难维护的就是区间的有效长度len

比如说有一个结点,范围是0~2,它的标记值是0,不是代表0~2这段都未被覆盖,而是代表0~2未被整体覆盖,所以其下的点0、1、2当前仍可能被覆盖着

为了解决这个问题,我们每次更新一个区间的len值后马上pushup,这样就可以保证区间len一直是正确的。

#include"cstdio"
#include"queue"
#include"cmath"
#include"stack"
#include"iostream"
#include"algorithm"
#include"cstring"
#include"queue"
#include"map"
#include"set"
#include"vector"
#define ll long long
#define mems(a,b) memset(a,b,sizeof(a))
#define ls pos<<1
#define rs pos<<1|1

using namespace std;
const int MAXN = 100500;
const int MAXE = 1005;
const int INF = 0x3f3f3f3f;

struct Node{
    int l,r;
    double len;
    int w;
}node[MAXN<<2];

struct seg{
    double l,r,h;
    int w;
    seg(){}
    seg(double a,double b,double c,int d):l(a),r(b),h(c),w(d){}
}line[MAXN<<1];
double h[MAXN<<1];
int n,m,p=1;

bool cmp(seg a,seg b){
    return a.h<b.h;
}

int get_pos(double x){
    int low=0,high=m,mid;
    while(low<=high){
        mid=(low+high)>>1;
        if(h[mid]==x) return mid;
        else if(h[mid]>x) high=mid-1;
        else low=mid+1;
    }
}

void pushup(int pos){
    if(node[pos].w) node[pos].len=h[node[pos].r+1]-h[node[pos].l];
    else if(node[pos].l==node[pos].r) node[pos].len=0;
    else node[pos].len=node[ls].len+node[rs].len;
}

void build(int l,int r,int pos){
    node[pos].l=l;
    node[pos].r=r;
    node[pos].len=0;
    node[pos].w=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(l,mid,ls);
    build(mid+1,r,rs);
}

void update(int l,int r,int pos,int w){
    if(l<=node[pos].l&&node[pos].r<=r){
        node[pos].w+=w;
        pushup(pos);            ///这里是关键- -
        return ;
    }
    int mid=(node[pos].l+node[pos].r)>>1;
    if(l<=mid) update(l,r,ls,w);
    if(r>mid) update(l,r,rs,w);
    pushup(pos);
}

int main(){
    //freopen("in.txt","r",stdin);
    while(scanf("%d",&n)&&n){
        printf("Test case #%d
",p++);
        for(int i=0;i<2*n;i+=2){
            double x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            line[i]=seg(x1,x2,y1,1);
            line[i+1]=seg(x1,x2,y2,-1);
            h[i]=x1;
            h[i+1]=x2;
        }
        sort(h,h+2*n);
        sort(line,line+2*n,cmp);
        m=0;
        for(int i=1;i<2*n;i++) if(h[i]!=h[i-1]) h[++m]=h[i]; ///去重
        double ans=0;
        build(0,m-1,1);
        for(int i=0;i<2*n-1;i++){
            int l=get_pos(line[i].l);
            int r=get_pos(line[i].r)-1;

            update(l,r,1,line[i].w);
            ans+=(line[i+1].h-line[i].h)*node[1].len;
        }
        printf("Total explored area: %.2lf

",ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/luxiaoming/p/5143376.html