POJ1151 Atlantis 线段树扫描线

扫描线终于看懂了。。。咕咕了快三个月$qwq$


对于所有的横线按纵坐标排序,矩阵靠下的线权值设为$1$,靠上的线权值设为$-1$,然后执行线段树区间加减,每次的贡献就是有效宽度乘上两次计算时的纵坐标之差。

$cnt$数组记录每个位置被覆盖的次数,$sum$数组用来记区间总长度(即有效宽度),所以每一次把$sum[1]$乘上高就行了。

注意到每个$r$都减了$1$,原因是原先的坐标是点的坐标,而现在一个位置代表一个区间。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ls (tr<<1)
#define rs (tr<<1|1)
#define ull unsigned long long
#define ll long long
#define R register int
using namespace std;
namespace Fread {
    static char B[1<<15],*S=B,*D=B;
    #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
    inline int g() {
        R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    } inline bool isempty(const char& ch) {return ch<=36||ch>=127;}
    inline void gs(char* s) {register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar()));}
}using Fread::g; using Fread::gs;
const int N=220;
struct ln {
    double l,r,x; int w; ln() {}
    ln(double Ll,double rr,double xx,int ww) {l=Ll,r=rr,x=xx,w=ww;}
    bool operator < (const ln& that) const {return x<that.x;}
}L[N]; int n,t,tot; double d[N];
int cnt[N<<2]; double sum[N<<2];
inline void upd(int tr,int l,int r) {
    if(cnt[tr]) sum[tr]=d[r+1]-d[l];
    else if(l==r) sum[tr]=0;
    else sum[tr]=sum[ls]+sum[rs];
}
inline void change(int tr,int l,int r,int LL,int RR,int vl) {
    if(LL<=l&&r<=RR) {cnt[tr]+=vl; upd(tr,l,r); return ;} R md=l+r>>1;
    if(LL<=md) change(ls,l,md,LL,RR,vl); if(RR>md) change(rs,md+1,r,LL,RR,vl); upd(tr,l,r);
}
signed main() {
#ifdef JACK
    freopen("NOIPAK++.in","r",stdin);
#endif
    while(scanf("%d",&n),n!=0) { memset(cnt,0,sizeof(cnt)),memset(sum,0,sizeof(sum)); tot=0;
        for(R i=1;i<=n;++i) { register double l,p,r,b;
            scanf("%lf%lf%lf%lf",&l,&p,&r,&b);
            d[++tot]=l,L[tot]=ln(l,r,p,1);
            d[++tot]=r,L[tot]=ln(l,r,b,-1);
        } sort(d+1,d+tot+1),sort(L+1,L+tot+1);
        n=unique(d+1,d+tot+1)-d-1; register double ans=0; 
        for(R i=1;i<=tot;++i) {
            R l=lower_bound(d+1,d+n+1,L[i].l)-d;
            R r=lower_bound(d+1,d+n+1,L[i].r)-d-1;
            change(1,1,n,l,r,L[i].w);
            ans+=sum[1]*(L[i+1].x-L[i].x);
        } printf("Test case #%d\nTotal explored area: %.2lf\n\n",++t,ans);
    }
}

2019.06.13

猜你喜欢

转载自www.cnblogs.com/Jackpei/p/11020484.html
今日推荐