美文网首页我爱编程
Atlantis HDU - 1542(线段树扫描线)

Atlantis HDU - 1542(线段树扫描线)

作者: weiers | 来源:发表于2018-04-14 15:48 被阅读0次

题目

http://acm.hdu.edu.cn/showproblem.php?pid=1542

题目大意

求所有矩形面积总和(矩形最多100个,坐标范围0~1e5)

算法思路

  • 从下往上扫描,计算出高度为y时处于矩形中的长度总和,再乘以到上一条边的高度,就为该段矩形面积。
  • 如何计算高度为y时处于矩形中的长度总和。扫描到矩形下边的时候,该段col值+1,表示此处被矩形覆盖,扫描到矩形上边时,该段col值-1,表示该段少了一个矩形覆盖。
  • 我们把扫描到的长度相加往上pushup,所求的值就存在了顶点中,即sum[1]。
    下面我们来看pushup函数:
void pushup(int rt,int l,int r){
   if(col[rt]) sum[rt]=x[r+1]-x[l];
   else if(l==r) sum[rt]=0;
   else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

col值大于0时表示其整一段被覆盖,计算该段长度。
col值等于0时,并不表示其没有被覆盖,可能其子段部分被覆盖。将子段数值相加往上推即可。

  • 因为其坐标范围过大,数组存不下,所以要将其横坐标离散化。但若对点离散化之后,原来的区间[l,r]变为[l,mid],[mid+1,r]时,就会缺少一段,所以线段的区间采用左闭右开,因此上方函数中sum[rt]=x[r+1]-x[l]

另外从别人的博客上盗了一张图帮助理解


image

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=210;
struct seg{
  double l,r,h;
  int s;
  bool operator< (const seg &b) const{
   return h<b.h;
  }s[maxn];
int col[maxn<<2];
double sum[maxn<<2];
double x[maxn<<2];

void pushup(int rt,int l,int r){
   if(col[rt]) sum[rt]=x[r+1]-x[l];//[ )
   else if(l==r) sum[rt]=0;
   else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

void update(int l,int r,int c,int rt,int ll,int rr){//l,r is fresh area
  if(ll>=l&&rr<=r){
    col[rt]+=c;
    pushup(rt,ll,rr);
    return;
  }

  int mid=(ll+rr)/2;
  if(l<=mid) update(l,r,c,rt*2,ll,mid);
  if(r>mid) update(l,r,c,rt*2+1,mid+1,rr);
  pushup(rt,ll,rr);
}

int main(){
    int n;int k=0;
    while(cin>>n&&n){
            k++;
            int cnt=0;
        for(int i=0;i<n;i++){
            double a,b,c,d;
            cin>>a>>b>>c>>d;
            s[cnt]=seg{a,c,b,1};//bottom line
            x[cnt++]=a;
            s[cnt]=seg{a,c,d,-1};//top line
            x[cnt++]=c;
        }
        sort(x,x+cnt);
        sort(s,s+cnt,cmp);
         int res=0;
        for(int i=1;i<cnt;i++){
            if(x[i]!=x[i-1])
                x[++res]=x[i];
        }
        memset(col,0,sizeof(col));
        memset(sum,0,sizeof(sum));
        double ans=0;
        for(int i=0;i<cnt-1;i++){
           int l=lower_bound(x,x+res+1,s[i].l)-x;//find the index after discretization
           int r=lower_bound(x,x+res+1,s[i].r)-x-1;//attention -1
            update(l,r,s[i].s,1,0,res);
            ans+=sum[1]*(s[i+1].h-s[i].h);
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n\n",k,ans);
    }
}

相关文章

  • Atlantis HDU - 1542(线段树扫描线)

    题目 http://acm.hdu.edu.cn/showproblem.php?pid=1542 题目大意 求所...

  • HDU1542(Atlantis)

    链接:https://vjudge.net/problem/HDU-1542思路:做了之前矩形面积的覆盖和周长的题...

  • 线段树专题整理

    待更新 线段树讲解(未读)线段树模板(未读) 模板 求区间总和 A - 敌兵布阵 HDU - 1166 题意 线段...

  • 扫描线+线段树

    扫描线+线段树解决的是矩形覆盖求面积/周长问题 面积版: 也就是给出若干个矩形,最后求总面积(重点是快速解决覆盖问...

  • HDU3974(Assign the task)

    链接:https://vjudge.net/problem/HDU-3974思路:终于明白了dfs序建线段树是什么...

  • HDU1540(Tunnel Warfare )

    链接:https://vjudge.net/problem/HDU-1540思路:这个题真的想透我感觉能明白线段树...

  • HDU 6047 Maximum Sequence

    hdu6047多校2-1003 这个问题,解法很多,线段树,优先队列,还有离线预处理A数组。下面这份代码就是离线预...

  • Segment Tree && RMQ

    段树(扫描线) 点树(扫描线) 区间合并

  • 线段树的训练

    HDU 1754 I Hate It求某个范围内数据的最值,为线段树的基本功能。在数据更新时使用不太熟练,另外由于...

  • HDU-4578-Transformation(线段树多重操作)

    Transformation思路:将区间的每个数都看成的形式操作1:  =  =  =操作2:  =  =  =操...

网友评论

    本文标题:Atlantis HDU - 1542(线段树扫描线)

    本文链接:https://www.haomeiwen.com/subject/dfslkftx.html