[POJ1151]Atlantis:离散化+扫描线+线段树

线段树的基本姿势。
对所有坐标离散化,扫描的同时打+1/-1标记并累加面积。
线段树每个叶结点i表示i-1~i这段有没有矩形覆盖,维护区间最大值和最小值,当一个区间的最小值>0时,直接加上这个区间;当一个区间的最大值==0时,直接跳过。
最后记住冒号后面有个空格,还有每组数据输出后要空一行。
讲的可能不清楚看代码就好了嘛QwQ
代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAXN=105;
int n,a[MAXN<<2],ql,qr,kk;
double inp[MAXN<<2],b[MAXN<<2],f[MAXN<<2];
struct Border{
    int x,y1,y2,typ;
}p[MAXN<<1];
bool cmp(Border u,Border v){
    return u.x<v.x;
}
#define mid ((l+r)>>1)
#define lc (o<<1)
#define rc ((o<<1)|1)
int maxn[MAXN<<4],minn[MAXN<<4],add[MAXN<<4];
void pushdown(int o,int l,int r){
    if(!add[o]) return;
    maxn[lc]+=add[o];
    maxn[rc]+=add[o];
    minn[lc]+=add[o];
    minn[rc]+=add[o];
    add[lc]+=add[o];
    add[rc]+=add[o];
    add[o]=0;
}
void upd(int o,int l,int r){
    if(ql<=l&&r<=qr){
        maxn[o]+=kk;
        minn[o]+=kk;
        add[o]+=kk;
        return;
    }
    pushdown(o,l,r);
    if(mid>=ql) upd(lc,l,mid);
    if(mid<qr) upd(rc,mid+1,r);
    maxn[o]=max(maxn[lc],maxn[rc]);
    minn[o]=min(minn[lc],minn[rc]);
}
double query(int o,int l,int r){
    if(minn[o]) return f[r]-f[l-1];
    pushdown(o,l,r);
    double ans=0.0;
    if(maxn[lc]) ans+=query(lc,l,mid);
    if(maxn[rc]) ans+=query(rc,mid+1,r);
    return ans;
}
int main(){
    int cas=0;
    while(~scanf("%d",&n)){
        if(!n) return 0;
        cas++;
        memset(maxn,0,sizeof maxn);
        memset(minn,0,sizeof minn);
        memset(add,0,sizeof add);
        for(int i=1;i<=(n<<2);i++){
            scanf("%lf",&inp[i]);
            b[i]=inp[i];
        }
        sort(b+1,b+(n<<2)+1);
        int siz=unique(b+1,b+(n<<2)+1)-b-1;
        for(int i=1;i<=(n<<2);i++){
            a[i]=lower_bound(b+1,b+siz+1,inp[i])-b;
            f[a[i]]=inp[i];
        }//离散化。 
        for(int i=1;i<=n;i++){
            int j=i*2-1,k=i*4-3;
            p[j].x=a[k];
            p[j].y1=a[k+1];
            p[j].y2=a[k+3];
            p[j].typ=1;
            j++;
            p[j]=p[j-1];
            p[j].x=a[k+2];
            p[j].typ=-1;
        }//输入矩形的位置。 
        sort(p+1,p+n*2+1,cmp);
        double ans=0.0;
        for(int i=1;i<(n<<1);i++){
            ql=p[i].y1+1,qr=p[i].y2,kk=p[i].typ;
            upd(1,1,n<<2);
            double len=query(1,1,n<<2);
            ans+=len*(f[p[i+1].x]-f[p[i].x]);
        }//扫描。 
        printf("Test case #%d\nTotal explored area: %.2lf\n\n",cas,ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9296412.html
今日推荐