线段树扫描线(求矩形面积并)小结

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define lowb(x) x&(-x)
#define N 105
#define LL long long
int n;

struct Line
{
    double l,r,h;
    int d;
    Line(){}
    Line(double a,double b,double c,int v)
    {
        l=a;r=b;
        h=c;d=v;
    }

}a[N<<2];
double all[N],sum[N<<2];
int cnt[N<<2];

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

void push_up(int l,int r,int rt)
{
    if(cnt[rt]){
    sum[rt]=all[r+1]-all[l];
    cout<<"sum"<<rt<<" = "<<sum[rt]<<endl;
    }
    else if(l==r){
        sum[rt]=0;
        cout<<"sum"<<rt<<"=0"<<endl;
    }
    else{
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
        cout<<"sum="<<rt<<"="<<(rt*2)<<"+"<<rt*2+1<<"="<<sum[rt]<<endl;
    }
}

void update(int l,int r,int L,int R,int k,int rt)
{
    cout<<"l,r, rt"<<l<<" "<<r<<" "<<rt<<endl;
    if(l>=L && r<=R)
    {
        cout<<"query "<<l<<" "<<r<<endl;
        cout<<"query rt="<<rt<<endl;
        cnt[rt]+=k;
        cout<<"cnt "<<rt<<"="<<cnt[rt]<<endl;
        push_up(l,r,rt);
        return ;
    }
    int m=(l+r)>>1;
    if(L<=m)update(l,m,L,R,k,rt<<1);
    if(R>m) update(m+1,r,L,R,k,rt<<1|1);
    push_up(l,r,rt);
}

int main()
{
   int kk=0;
   while(cin>>n&&n)
   {
       double x1,y1,x2,y2;
       for(int i=1;i<=n;i++)
       {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            a[i]=Line(x1,x2,y1,1);//离散化过程
            a[i+n]=Line(x1,x2,y2,-1);
            all[i]=x1;all[i+n]=x2;
       }
       n<<=1;

       sort(all+1,all+1+n);//离散化x坐标从下往上扫描
       sort(a+1,a+1+n,cmp);//按高度排序
       int m=unique(all+1,all+1+n)-all-1;//不同点的个数

       double ans=0;
       memset(cnt,0,sizeof(cnt));
       memset(sum,0,sizeof(sum));

       for(int i=1;i<n;i++)
       {
           int l=lower_bound(all+1,all+1+m,a[i].l)-all;//从下往上扫描找到该矩形的左右端点对应在x轴的下标
           int r=lower_bound(all+1,all+1+m,a[i].r)-all;
           cout<<l<<" "<<r-1<<" "<<a[i].d<<endl;
           update(1,m-1,l,r-1,a[i].d,1);//更新该区间的值
           cout<<"sum"<<sum[1]<<endl;  
           ans+=sum[1]*(a[i+1].h-a[i].h);
           cout<<"ans="<<ans<<endl;
       }
       printf("Test case #%d\n",++kk);
       printf("Total explored area: %.2f\n",ans);
       printf("\n");
   }
}
从调试过程可以看出:
第一次更新区间【1,2】d=1的时候sum【2】=10;
当 第三次查询【1,2】d=-1d的时候时候cnt[2]=0;
此时需要从它的子节点获取信息;
即此时执行sum2=sum4+sum5;
因为在此之前得到了sum5 =5
所以1-2区间得到更新。
同样的方法去处理3-4区间
划分区间的方法:
将每一段看成一个点:
例如离散化后的x坐标有4个
x1 x2 x3 x4
左闭右开

调试过程:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值