zoukankan      html  css  js  c++  java
  • 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
    Total explored area: %.2lf
    
    ",++t,ans);
        }
    }

    2019.06.13

  • 相关阅读:
    关于MySQL INT类型长度的疑惑
    uwp 的锁屏功能
    QT5 动态链接库的创建和使用
    Qt 自定义事件的实现
    学习k8s本地虚拟机安装minikube
    建议收藏!细说HashMap实现,Hash冲突模拟思路讲解。
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees(dp)
    574 React系列(一)
    如何在Win7电脑上增加新磁盘分区?
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11020484.html
Copyright © 2011-2022 走看看