zoukankan      html  css  js  c++  java
  • bzoj5328: [Sdoi2018]物理实验

    果然我还是太菜了,爆了一天才过。。。。隔壁肉丝都不知道喊了多少句哎╮(╯▽╰)╭我又A了什么傻逼题(然鹅就是wf和国集的题QWQ)

    其实这个题就是个裸题,但是我就是不会。。。

    这个题第一步就是明显的旋转坐标系(不会的百度),注意要先平移坐标系再旋转

    然后问题就变成x轴上下有一些线段,考虑覆盖长度为L的一段区间,看看区间内最接近x轴的线段的长度和(也可以直接按题意理解,好像更好懂)

    线段是斜着的很难搞,但是假如覆盖了l~r的区间,那么也可以通过三角函数搞出线段长度

    可以先弄一个类似离散化的东西,我的意思是每个线段的左右端点的x坐标为断点,相邻x坐标之间可以看成一段(大概就是这样不懂评论我)

    主要问题在处理出每一段最接近x轴的线段是那一条,假如搞定了这个东西,我们可以正反枚举每个段,然后能要段就要,再加上下一个段的一部分更新答案,这个双指针扫一下就好

    考虑按端点的x坐标上扫描线,对于线段有一个关键的性质,就是线段不相交,这里隐含着这么一个东西:假如线段u的左端点的x坐标较小,线段v的左端点在线段u的上方/下方,直到u被删除线段的上下关系都是不变的,否则线段就相交了

    换句话说,不相交满足对于在任意一条线段的左右端点x坐标框住的区间中,任意一条线段和这一条线段的上下关系不变

    那么有这个东西就可以做了,用set维护一下上方最下的线段和下方最上的线段即可

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<set>
    using namespace std;
    typedef long double LD;
    const int _=1e2;
    const int maxn=1e4+_;
    const LD eps=1e-12;
    LD sqr(LD x){return x*x;}
    int n;
    
    struct point{LD x,y; point(){} point(LD X,LD Y){x=X,y=Y;}};
    LD getdis(point p1,point p2){return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));}
    LD slope(point p1,point p2){return (p2.y-p1.y)/(p2.x-p1.x);}
    LD multi(point p1,point p2,point p0)
    {
        LD x1,y1,x2,y2;
        x1=p1.x-p0.x;
        y1=p1.y-p0.y;
        x2=p2.x-p0.x;
        y2=p2.y-p0.y;
        return x1*y2-x2*y1;
    }
    
    //------------------------------------------------def-----------------------------------------------------
    
    struct board
    {
        point A,B;
        LD g;//长度变化的比值 1/cos
        void getg(){g=getdis(A,B)/fabs(A.x-B.x);}
    }b[maxn];bool cmp(board b1,board b2){return b1.A.y<b2.A.y;}
    bool bbbbcmp(board b1,board b2){return b1.A.x<b2.A.x;}
    
    LD co,si;
    point rot(point p){return point(p.x*co-p.y*si,p.y*co+p.x*si);}
    void rotate()
    {
        LD d=getdis(b[n+1].A,b[n+1].B);
        co=fabs(b[n+1].A.x-b[n+1].B.x)/d;
        si=fabs(b[n+1].A.y-b[n+1].B.y)/d;
        if(b[n+1].A.x<b[n+1].B.x&&b[n+1].A.y<b[n+1].B.y)si=-si;
        
        for(int i=1;i<=n;i++)
        {
            b[i].A.x-=b[n+1].A.x,b[i].A.y-=b[n+1].A.y;
            b[i].B.x-=b[n+1].A.x,b[i].B.y-=b[n+1].A.y;
            
            b[i].A=rot(b[i].A);
            b[i].B=rot(b[i].B);
            if(b[i].A.x>b[i].B.x)swap(b[i].A,b[i].B);
            b[i].getg();
            
    //        printf("%.10Lf %.10Lf %.10Lf %.10Lf
    ",b[i].A.x,b[i].A.y,b[i].B.x,b[i].B.y);
        }
    }
    
    //---------------------------------------------------rotate-------------------------------------------------
    
    LD xx[2*maxn];int xlen;
    bool xx_cmp(LD x1,LD x2){return x1<x2;}
    int up[2*maxn],dp[2*maxn];//xx[i]~xx[i-1]这一段被那条线段覆盖着 
    
    struct seg
    {
        int id;
        seg(){} seg(int ID){id=ID;}
        friend bool operator <(seg s1,seg s2)
        {
            int x=s1.id,y=s2.id;
            if(x<y)return multi(b[x].B,b[y].A,b[x].A)>0;
            else   return multi(b[y].B,b[x].A,b[y].A)<0;
        }
        friend bool operator >(seg s1,seg s2)
        {
            int x=s1.id,y=s2.id;
            if(x<y)return multi(b[x].B,b[y].A,b[x].A)<0;
            else   return multi(b[y].B,b[x].A,b[y].A)>0;
        }
    };set< seg,less<seg> >us;set< seg,greater<seg> >ds;
    
    struct qq{int op,p;seg s; qq(){} qq(int OP,int P,seg S){op=OP,p=P,s=S;}}uq[2*maxn],dq[2*maxn];int uqlen,dqlen;
    bool qqqqcmp(qq q1,qq q2){return q1.p==q2.p?q1.op>q2.op:q1.p<q2.p;}
    
    int lb(LD d)
    {
        int l=1,r=xlen;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(fabs(xx[mid]-d)<=eps)return mid;
            if(xx[mid]>d)r=mid-1;
            else l=mid+1;
        }
    }
    void cover(int l1,int r1,int l2,int r2)
    {
        sort(b+l1,b+r1+1,bbbbcmp);
        sort(b+l2,b+r2+1,bbbbcmp);
        uqlen=dqlen=0;
        for(int i=l1;i<=r1;i++)
        {
            uq[++uqlen]=qq( 1,lb(b[i].A.x)+1,seg(i));
            uq[++uqlen]=qq(-1,lb(b[i].B.x),seg(i));
        }
        for(int i=l2;i<=r2;i++)
        {
            dq[++dqlen]=qq( 1,lb(b[i].A.x)+1,seg(i));
            dq[++dqlen]=qq(-1,lb(b[i].B.x),seg(i));
        }
        
        us.clear(),ds.clear();
        sort(uq+1,uq+uqlen+1,qqqqcmp);
        sort(dq+1,dq+dqlen+1,qqqqcmp);
        int utp=1,dtp=1;
        for(int i=1;i<=xlen;i++)
        {
            while(utp<=uqlen&&uq[utp].p==i&&uq[utp].op==1)us.insert(uq[utp].s),utp++;
            while(dtp<=dqlen&&dq[dtp].p==i&&dq[dtp].op==1)ds.insert(dq[dtp].s),dtp++;
            
            if(!us.empty())up[i]=(*us.begin()).id; else up[i]=-1;
            if(!ds.empty())dp[i]=(*ds.begin()).id; else dp[i]=-1;
            
            while(utp<=uqlen&&uq[utp].p==i&&uq[utp].op==-1)us.erase(uq[utp].s),utp++;
            while(dtp<=dqlen&&dq[dtp].p==i&&dq[dtp].op==-1)ds.erase(dq[dtp].s),dtp++;
        }
    }
    
    //-----------------------------------------------cover------------------------------------------------------
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n+1;i++)
                scanf("%Lf%Lf%Lf%Lf",&b[i].A.x,&b[i].A.y,&b[i].B.x,&b[i].B.y);
            scanf("%Lf",&b[n+1].g);
            if(b[n+1].A.x>b[n+1].B.x)swap(b[n+1].A,b[n+1].B);
            rotate();
            
            //....step1.......
            
            int pp=n+1; sort(b+1,b+n+1,cmp);
            xlen=0;
            for(int i=1;i<=n;i++)
            {
                if(b[i].A.y>0&&pp==n+1)pp=i;
                xx[++xlen]=b[i].A.x;
                xx[++xlen]=b[i].B.x;
            }
            sort(xx+1,xx+xlen+1);
            int tp=1;
            for(int j=2;j<=xlen;j++)
                if(fabs(xx[j]-xx[tp])>eps)xx[++tp]=xx[j];
            xlen=tp;
            cover(pp,n,1,pp-1);
            
            //....step2.......
            
            LD ans=0,sum=0;
            int j=1;
            for(int i=2;i<=xlen;i++)
            {
                while(j<xlen&&(xx[j+1]-xx[i-1])<=b[n+1].g)
                {
                    j++;
                    if(up[j]!=-1)sum+=(xx[j]-xx[j-1])*b[up[j]].g;
                    if(dp[j]!=-1)sum+=(xx[j]-xx[j-1])*b[dp[j]].g;
                }
                LD num=0;
                if(j<xlen)
                {
                    if(up[j+1]!=-1)num+=min(xx[j+1]-xx[j],b[n+1].g-(xx[j]-xx[i-1]))*b[up[j+1]].g;
                    if(dp[j+1]!=-1)num+=min(xx[j+1]-xx[j],b[n+1].g-(xx[j]-xx[i-1]))*b[dp[j+1]].g;
                }
                ans=max(ans,sum+num);
                if(up[i]!=-1)sum-=(xx[i]-xx[i-1])*b[up[i]].g;
                if(dp[i]!=-1)sum-=(xx[i]-xx[i-1])*b[dp[i]].g;
                
    //            printf("%.10Lf %.10Lf %.10Lf
    ",xx[i]-xx[i-1],b[up[i]].g,b[dp[i]].g);
            }
            j=xlen;sum=0;
            for(int i=xlen;i>1;i--)
            {
                while(j>1&&(xx[i]-xx[j-1])<=b[n+1].g)
                {
                    if(up[j]!=-1)sum+=(xx[j]-xx[j-1])*b[up[j]].g;
                    if(dp[j]!=-1)sum+=(xx[j]-xx[j-1])*b[dp[j]].g;
                    j--;
                }
                LD num=0;
                if(j>1)
                {
                    if(up[j]!=-1)num+=min(xx[j]-xx[j-1],b[n+1].g-(xx[i]-xx[j]))*b[up[j]].g;
                    if(dp[j]!=-1)num+=min(xx[j]-xx[j-1],b[n+1].g-(xx[i]-xx[j]))*b[dp[j]].g;
                }
                ans=max(ans,sum+num);
                if(up[i]!=-1)sum-=(xx[i]-xx[i-1])*b[up[i]].g;
                if(dp[i]!=-1)sum-=(xx[i]-xx[i-1])*b[dp[i]].g;
            }
            
            printf("%.10Lf
    ",ans);
    //        break;
            //....step3.......
        }
        
        return 0;
    }
  • 相关阅读:
    HDU 1584 蜘蛛牌(DFS)
    HDU 1800 Flying to the Mars(贪心)
    zsh: command not found: java (xxx)
    Deepin20安装Mysql8
    Deepin全局菜单
    Ubuntu PPA 解读
    Node安装与配置
    Windows安装配置Maven
    idea 安装 Vue 插件没有Vue component选项
    Linux桌面系统创建应用程序快捷方式
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10561320.html
Copyright © 2011-2022 走看看