HDU1255 线段树+扫描线

题意:n个矩形求出被两个以上矩形覆盖的面积之和

第一种方法每次都查找到最底层的节点,并计算其对总面积的贡献。这样比较好想也比较好写,但是比较慢,差不多要1s。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ld d<<1
#define rd d<<1|1
const int N = 2005;
double y[N<<2];
struct seg
{
    double x, y1,y2;
    int flag;
    bool operator <(const seg a) const
    {
        return x < a.x;
    }
}a[N<<2];
struct node
{
    double x;
    int cover;
}tr[N << 3];
void build(int d, int l, int r)
{
    tr[d].x = -1;
    tr[d].cover = 0;
    if(r - l == 1) return;
    int m = (l+r) >>1;
    build(ld,l,m); build(rd,m,r);
    return;
}
double query(int d, int l, int r, double ql,double qr, double x, int fl)
{
    double ans = 0;
    if(r -  l == 1)
    {
        if(tr[d].cover >= 2)   ans =  (y[r] - y[l])*(x - tr[d].x);
        tr[d].x = x; tr[d].cover += fl;
        return ans ;
    }
        int m = (l+r) >>1;
        if(ql < y[m]) ans += query(ld,l,m,ql,qr,x,fl);
        if(y[m] < qr) ans += query(rd,m,r,ql,qr,x,fl);
        return ans;
}
int main()
{
     int times; scanf("%d",×);
     while(times --)
     {
         int n; scanf("%d",&n);
         int k = 0;
         for(int i = 0; i < n; i++)
         {
             double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
             a[k].x = x1,a[k].y1 = y1,a[k].y2 = y2; a[k].flag = 1;y[k++] = y1;
             a[k].x = x2,a[k].y1 = y1,a[k].y2 = y2; a[k].flag = -1; y[k++] = y2;
         }
         sort(y,y+k);
         sort(a,a+k);
         int cony = unique(y,y+k) - y;
         build(1,0,cony - 1);
         double ans = 0;
         for(int i = 0; i < k; i++)
         {
             ans += query(1,0,cony - 1,a[i].y1,a[i].y2,a[i].x,a[i].flag);
         }
         printf("%.2f\n",ans);
     }
}

第二种方法,每次查找到待插入的区间就不往下继续查找了,节点的len保存已经被覆盖两次以上的区间的总长度,所以只需要用本次更新前的根节点的len值,和上次插入的边的x值进行计算,即可算出本次操作的贡献值。这个方法会稍微快一些,因为不需要每次都递归到最深层,只需要在递归返回的过程中依次维护父节点的值就好,用时在300ms以内。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ld d<<1
#define rd d<<1|1
const int N = 2005;
double y[N<<2];
struct seg
{
    double x, y1,y2;
    int flag;
    bool operator <(const seg a) const
    {
        return x < a.x;
    }
}a[N<<2];
struct node
{
    double x,len,telen;
    int cover;
}tr[N << 3];
void build(int d, int l, int r)
{
    tr[d].x = -1;
    tr[d].cover = 0;
    if(r - l == 1) return;
    int m = (l+r) >>1;
    build(ld,l,m); build(rd,m,r);
    return;
}
void update(int d, int l, int r)
{
    if(tr[d].cover >= 2)
    {
        tr[d].len = y[r] - y[l];
        tr[d].telen = 0;
        return ;
    }
    if(tr[d].cover == 1)
    {
        if(r - l == 1) tr[d].len = 0;
        else tr[d].len = tr[ld].len + tr[rd].len+tr[ld].telen + tr[rd].telen;
        tr[d].telen = y[r] - y[l] - tr[d].len;
        return ;
    }
    if(tr[d].cover == 0)
    {
        if(r - l == 1) tr[d].len = tr[d].telen = 0;
        else
        tr[d].telen = tr[ld].telen + tr[rd].telen,tr[d].len = tr[ld].len + tr[rd].len;
    }
}
void query(int d, int l, int r, double ql,double qr, double x, int fl)
{
    if(ql <= y[l] && y[r] <= qr)
    {
      tr[d].cover += fl;
      update(d,l,r);
      return ;
    }
    if(r - l == 1) return ;
        int m = (l+r) >>1;
        if(ql < y[m])query(ld,l,m,ql,qr,x,fl);
        if(y[m] < qr)query(rd,m,r,ql,qr,x,fl);
        update(d,l,r);
        return ;
}
int main()
{
     int times; scanf("%d",×);
     while(times --)
     {
         int n; scanf("%d",&n);
         int k = 0;
         for(int i = 0; i < n; i++)
         {
             double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
             a[k].x = x1,a[k].y1 = y1,a[k].y2 = y2; a[k].flag = 1;y[k++] = y1;
             a[k].x = x2,a[k].y1 = y1,a[k].y2 = y2; a[k].flag = -1; y[k++] = y2;
         }
         sort(y,y+k);
         sort(a,a+k);
         int cony = unique(y,y+k) - y;
         build(1,0,cony - 1);
         double ans = 0.0;
         double lalen = 0;
         for(int i = 0; i < k; i++)
         {
            query(1,0,cony - 1,a[i].y1,a[i].y2,a[i].x,a[i].flag);
            if(i >= 1)
            {
                ans += lalen *(a[i].x - a[i -1].x);
            }
            lalen = tr[1].len;
         }
         printf("%.2f\n",ans);
     }
}



猜你喜欢

转载自blog.csdn.net/zlatan10/article/details/77370611
今日推荐