首页 > 代码库 > HDU 1255 覆盖的面积(线段树+扫描线)

HDU 1255 覆盖的面积(线段树+扫描线)

题目地址:HDU 1255

这题跟面积并的方法很像,只不过需要再加一个变量。

刚开始我以为直接用那个变量就行,只不过判断是否大于0改成判断是否大于1。但是后来发现了个问题,因为这个没有下放,没延迟,比如,在父节点上加了一次1,在该父节点的子节点上又加了一次1,但是这时候所有的结点仍然没有达到2的,但是实际上子节点已经达到2了。这时候可以再加一个变量。那个变量用来保存覆盖数大于等于0的情况,这样的话当计算大于1的覆盖节点的时候,当判断为1的时候就要加上子节点的所有情况,因为字节点是大于0的,加上子节点的说明该父节点也是大于1的。

代码如下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
int lazy[10000], cnt;
double sum[10000], c[10000], once[10000];
struct node
{
    double l, r, h;
    int f;
} edge[100000];
int cmp(node x, node y)
{
    return x.h<y.h;
}
void add(double l, double r, double h, int f)
{
    edge[cnt].l=l;
    edge[cnt].r=r;
    edge[cnt].h=h;
    edge[cnt++].f=f;
}
void PushUp(int l, int r, int rt)
{
    if(lazy[rt]>=2)
    {
        once[rt]=sum[rt]=c[r+1]-c[l];
    }
    else if(lazy[rt]==1)
    {
        once[rt]=c[r+1]-c[l];
        if(l==r)
        {
            sum[rt]=0;
        }
        else
            sum[rt]=once[rt<<1]+once[rt<<1|1];
    }
    else
    {
        if(l==r)
            once[rt]=sum[rt]=0;
        else
        {
            once[rt]=once[rt<<1]+once[rt<<1|1];
            sum[rt]=sum[rt<<1]+sum[rt<<1|1];
        }
    }
}
void update(int ll, int rr, int x, int l, int r,int rt)
{
    if(ll<=l&&rr>=r)
    {
        lazy[rt]+=x;
        PushUp(l,r,rt);
        return ;
    }
    int mid=l+r>>1;
    if(ll<=mid) update(ll,rr,x,lson);
    if(rr>mid) update(ll,rr,x,rson);
    PushUp(l,r,rt);
}
int erfen(double x, int high)
{
    int low=0, mid;
    while(low<=high)
    {
        mid=low+high>>1;
        if(c[mid]==x)
            return mid;
        else if(c[mid]>x)
            high=mid-1;
        else
            low=mid+1;
    }
}
int main()
{
    int t, n, i, j, k;
    double x1, x2, y1, y2, ans;
    scanf("%d",&t);
    while(t--)
    {
        ans=0;
        memset(sum,0,sizeof(sum));
        memset(lazy,0,sizeof(lazy));
        memset(once,0,sizeof(once));
        scanf("%d",&n);
        k=0;
        cnt=0;
        for(i=0; i<n; i++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            c[k++]=x1;
            c[k++]=x2;
            add(x1,x2,y1,1);
            add(x1,x2,y2,-1);
        }
        sort(edge,edge+2*n,cmp);
        sort(c,c+k);
        for(i=0; i<2*n-1; i++)
        {
            int l=erfen(edge[i].l,2*n-1);
            int r=erfen(edge[i].r,2*n-1);
            //printf("%d %d\n",l,r);
            update(l,r-1,edge[i].f,0,2*n-1,1);
            ans+=sum[1]*(edge[i+1].h-edge[i].h);
            //printf("%.2lf   %.2lf\n",sum[1],edge[i+1].h-edge[i].h);
        }
        printf("%.2lf\n",ans);
    }
    return 0;
}