• 几何+二分——cf1016E


    /*
    把所有的阻挡物按x轴排序,对于每个点i,二分去找左右两端点[l,r],求[l,r]未被阻挡的距离 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 400005
    #define ll long long
     
    typedef double db;
    const db eps=1e-6;
    const db pi=acos(-1);
    int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;}
    int cmp(db k1,db k2){return sign(k1-k2);}
    int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内 
    struct point{
        db x,y;
        point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
        point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
        point operator * (db k1) const{return (point){x*k1,y*k1};}
        point operator / (db k1) const{return (point){x/k1,y/k1};}
        int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
        db abs(){return sqrt(x*x+y*y);}
        db abs2(){return x*x+y*y;}
        db dis(point k1){return ((*this)-k1).abs();}
        point unit(){db w=abs(); return (point){x/w,y/w};}
    };
    int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
    db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
    db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
    point getLL(point k1,point k2,point k3,point k4){
        db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3); return (k1*w2+k2*w1)/(w1+w2);
    }
    struct Seg{
        int l,r;
    }s[N];
    ll n,sy,a,b,sum[N];//sum[i]表示第i块隔板的长度 
    point L,R,k1,k2,k3;
     
    int main(){
        cin>>sy>>a>>b>>n;
        L=(point){a*1.0,sy*1.0},R=(point){b*1.0,sy*1.0};
        for(int i=1;i<=n;i++)
            scanf("%d%d",&s[i].l,&s[i].r);
        for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+s[i].r-s[i].l; 
        int q;cin>>q;
        while(q--){
            scanf("%lf%lf",&k1.x,&k1.y);
            k2=getLL(k1,L,(point){-1,0},(point){1,0});//和x轴左端交点
            k3=getLL(k1,R,(point){-1,0},(point){1,0});//和x轴右端交点
            
            if(k2.x>=s[n].r || k3.x<=s[1].l){//没阻挡物 
                cout<<0<<'
    ';continue;
            }
            
            int l=1,r=n,mid,pos1=n+1;
            while(l<=r){//找最靠左的左端点>=k2.x的段 
                mid=l+r>>1;
                if(s[mid].l>=k2.x)
                    pos1=mid,r=mid-1;
                else l=mid+1;
            }
            
            l=1,r=n;
            int pos2=0;
            while(l<=r){//找最靠右的右端点<=k3.x的段 
                mid=l+r>>1;
                if(s[mid].r<=k3.x)
                    pos2=mid,l=mid+1;
                else r=mid-1; 
            }
            
            db len=0;
            if(pos2>=pos1)len+=sum[pos2]-sum[pos1-1];
            if(pos1==pos2+2){
                len=k3.x-k2.x;//在同一条线段上相交
                printf("%.10lf
    ",len/(k3.x-k2.x)*(b-a)); 
                continue;
            }
            if(pos1>1) //前一项的长度 
                len+=max(0.0,s[pos1-1].r-k2.x);
            if(pos2<n) //后一项的长度 
                len+=max(0.0,k3.x-s[pos2+1].l);
            printf("%.10lf
    ",len/(k3.x-k2.x)*(b-a));
        }
    }
  • 相关阅读:
    导出EXCEL 没有乱码,已确认可以使用, 转自csdn
    发送微信模板消息 已测试通过
    mysql 无法启动 innodb 报错 1067
    redis3.0集群搭建
    centos下编译openjdk1.8
    Redis无法远程访问
    记一次优化的的意外收获
    mysql的基础优化
    关于inputStream.read()返回值的问题
    rest风格的url接收
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12551357.html
Copyright © 2020-2023  润新知