Atlantis HDU

来源:互联网 发布:linux 启动命令模式 编辑:程序博客网 时间:2024/06/07 11:09

给出一堆矩形的左下右上坐标,问矩形面积并

扫描线的本质就是把图形分层,每层的边界就是一条“扫描线”

这里的做法是把图形按照y坐标分成一条条等高的长条,

让长条不断加入我们的图形,即扫描的过程

{

对于每一个长条,它对图形的影响取决于它的长度,它的高度还有它是组合图的入边还是出边(取决于我们扫的方向,这里从下往上扫)

那么我们维护的信息就是这个时间点,x轴上被覆盖的总面积,

这个数据的维护用到了线段树,

首先离散化x轴上所有出现的坐标

如果这个扫描线是入边,那么对应区间的【完全覆盖次数】+1,反之-1,这是区间修改

pushup过程中,

1如果这个节点被完全覆盖,那么向上传递这个区间的长度,

2否则如果是叶子节点,上传0;

3否则向上传递子节点覆盖的总长度,这里注意,整个过程中不需要pushdown操作,所以我们把1,3分成两种情况

}

这条扫描线的信息更新完毕,我们就需要把这条扫描线到下一条扫描线的距离×总区间覆盖长度的值加进最后的答案

代码:

#include<bits/stdc++.h>using namespace std;#define ll long longconst int maxn=210;struct Node{    double l,r,h;    int d;    Node(){};    Node(double a,double b,double c,int d):l(a),r(b),h(c),d(d){}    bool operator<(const Node &b)const{        return h<b.h;    }}node[maxn];struct st{    int cover;    double sum;}ST[maxn<<2];double X[maxn];void pushup(int l,int r,int rt){    if(ST[rt].cover)ST[rt].sum=X[r+1]-X[l];    else if(l==r)ST[rt].sum=0;    else ST[rt].sum=ST[rt<<1].sum+ST[rt<<1|1].sum;}void build(int l,int r,int rt){    if(l==r){        ST[rt].cover=0;        ST[rt].sum=0;        return;    }    int m=(l+r)>>1;    build(l,m,rt<<1);    build(m+1,r,rt<<1|1);    pushup(l,r,rt);}void update(int a,int b,int c,int l,int r,int rt){    if(a<=l&&b>=r){        ST[rt].cover+=c;        pushup(l,r,rt);        return;    }    int m=(l+r)>>1;    if(a<=m)update(a,b,c,l,m,rt<<1);    if(b>m)update(a,b,c,m+1,r,rt<<1|1);    pushup(l,r,rt);}int main(){    int n;    int kase=0;    while(~scanf("%d",&n)&&n){        memset(node,0,sizeof(node));        memset(ST,0,sizeof(ST));        int tot=0;        for(int i=1;i<=n;i++){            double x1,y1,x2,y2;            scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);            X[++tot]=x1;            node[tot]=Node(x1,x2,y1,1);            X[++tot]=x2;            node[tot]=Node(x1,x2,y2,-1);        }                  sort(X+1,X+tot+1);        sort(node+1,node+tot+1);        int k=1;        for(int i=2;i<=tot;i++){            if(X[i]!=X[i-1]){                X[++k]=X[i];            }        }        build(1,k-1,1);        double ans=0;                for(int i=1;i<tot;i++){            int l=lower_bound(X+1,X+1+k,node[i].l)-X;            int r=lower_bound(X+1,X+1+k,node[i].r)-X-1;            update(l,r,node[i].d,1,k-1,1);            ans+=ST[1].sum*(node[i+1].h-node[i].h);        }        printf("Test case #%d\nTotal explored area: %.2lf\n\n",++kase,ans);    }}

吐槽一句,省赛真的太遗憾了,要是把题目分配优化一下结果就会好得多,

“至少你要敲一下啊”,赛后学长们是这么讲的,

没有快速打出代码的自信,我也就放过了猜出的正解,

打出代码,才有一交的机会,在最后一刻交一发,哪怕wa起码不会留下遗憾

保持冷静地快速敲出代码,这就是我接下来训练的目标吧

原创粉丝点击