zoukankan      html  css  js  c++  java
  • jzoj4640. 【GDOI2017模拟7.15】妖怪

    Description

    在这里插入图片描述

    Input

    在这里插入图片描述

    Output

    在这里插入图片描述

    Sample Input

    3
    1 1
    1 2
    2 2

    Sample Output

    8.0000
    在这里插入图片描述

    Data Constraint

    在这里插入图片描述

    题解

    我还挺喜欢数学的呢
    这题一眼看上去不会,化化式子没想到未知数竟然是一个反比例+一次函数的样子。
    长这样:ax+bxfrac a x+bx
    当时心态就没了。
    原来这玩意是一个在高中叫做双勾函数(或对勾函数或耐克函数
    很好,于是我们就看看这个玩意长什么样——
    在这里插入图片描述
    既然是长这个样子,那么应该就有一个顶点(最小点)。
    利用均值不等式可以得到——
    (aba,2ab)(frac{sqrt{ab}}a,2sqrt{ab})
    由于图中有很多很多的双勾函数,那么其中必然有一些线没有用的。
    我们考虑删去这些没有用的

    怎么删?
    首先我们对于任意两点——满足
    ai<ajyi<yja_i<a_j且y_i<y_j(答案)
    那么
    ai+bi+aix+bix<aj+bj+ajx+bjxa_i+b_i+a_i*x+frac{b_i}{x}<a_j+b_j+a_j*x+frac{b_j}{x}
    化一波式子得到:
    x>bibjajaix>frac{b_i-b_j}{a_j-a_i}
    c[i,j]=bibjajaic[i,j]=frac{b_i-b_j}{a_j-a_i}
    则我们对于一个c[i,j]>c[j,k]c[i,j]>c[j,k]那么j这个点就是没有用的。
    所以说,我们就得到一个序列dd,序列满足c[di1,di]<c[di,di+1]c[d_{i-1},d_i]<c[d_i,d_{i+1}]
    这个东东是递增的。
    那么我们发现:当xxc[di1,di]c[d_{i-1},d_i]c[di,di+1]c[d_i,d_{i+1}]这段区间内时,did_i的函数值是最大的。
    因此,我们在did_i的函数上判断这段区间的最小值即可。
    怎么判断?可能有三种情况:
    1、在顶点左边。
    2、在顶点右边。
    3、横跨顶点。

    O(n)O(n)求即可。

    代码

    var
            i,j,k,l,n,m,now:longint;
            a,b,d:array[0..1000003] of longint;
            op,oq,x,y,ans,aa,bb:extended;
    function min(x,y:extended):extended;
    begin
            if x<y then exit(x);exit(y);
    end;
    procedure qsort(l,r:longint);
    var
            i,j,m,m1:longint;
    begin
            i:=l;j:=r;
            m:=a[(l+r) div 2];
            m1:=b[(l+r) div 2];
            repeat
                    while (a[i]<m) or ((a[i]=m) and (b[i]<m1)) do inc(i);
                    while (a[j]>m) or ((a[j]=m) and (b[j]>m1)) do dec(j);
                    if i<=j then
                    begin
                            a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
                            b[0]:=b[i];b[i]:=b[j];b[j]:=b[0];
                            inc(i);dec(j);
                    end;
            until i>j;
            if l<j then qsort(l,j);
            if r>i then qsort(i,r);
    end;
    function pd(i:longint):boolean;
    var
            x,y,op,oq:extended;
    begin
            x:=b[d[now]]-b[d[now-1]];
            y:=a[d[now-1]]-a[d[now]];
            op:=x/y;
            x:=b[i]-b[d[now]];
            y:=a[d[now]]-a[i];
            oq:=x/y;
            if op>oq then exit(true);
            exit(false);
    end;
    begin
            //assign(input,'monster.in');reset(input);
            readln(n);
            for i:=1 to n do
            begin
                    read(a[i],b[i]);
            end;
            qsort(1,n);
            now:=1;
            d[1]:=1;
            for i:=2 to n do
            begin
                    if a[i]>a[1] then
                    begin
                            inc(now);
                            d[now]:=i;
                            j:=i;
                            break;
                    end;
            end;
            for i:=j+1 to n do
            begin
                    if a[i]>a[d[now]] then
                    begin
                            while (now>=2) and (pd(i)) do dec(now);
                            inc(now);d[now]:=i;
                    end;
            end;
            ans:=maxlongint;
            for i:=2 to now-1 do
            begin
                    x:=b[d[i]]-b[d[i-1]];
                    y:=a[d[i-1]]-a[d[i]];
                    op:=x/y;
                    x:=b[d[i+1]]-b[d[i]];
                    y:=a[d[i]]-a[d[i+1]];
                    oq:=x/y;
                    aa:=a[d[i]];
                    bb:=b[d[i]];
                    if op>sqrt(aa*bb)/aa then ans:=min(ans,aa*op+bb/op+aa+bb);
                    if oq<sqrt(aa*bb)/aa then ans:=min(ans,aa*oq+bb/oq+aa+bb);
                    if (op<=sqrt(aa*bb)/aa) and (oq>=sqrt(aa*bb)/aa) then ans:=min(ans,2*sqrt(aa*bb)+aa+bb);
            end;
            x:=b[d[now]]-b[d[now-1]];
            y:=a[d[now-1]]-a[d[now]];
            aa:=a[d[now]];bb:=b[d[now]];
            op:=x/y;
            if op>sqrt(aa*bb)/aa then ans:=min(ans,aa*op+bb/op+aa+bb)
            else ans:=min(ans,2*sqrt(aa*bb)+aa+bb);
            writeln(ans:0:4);
    end.
    
  • 相关阅读:
    分享分享JavaScript100例-仅供参考
    为每个页面加上Session判断
    Javascript实现真实字符串剩余字数提示
    格式与文件扩展名指定的格式不一致
    谈谈Github Universe 2019
    合并两个有序链表的golang实现
    二叉搜索树的最近公共祖先的golang实现
    验证二叉搜索树的golang实现
    三数之和的golang实现
    有效的字母异位词的golang实现
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148359.html
Copyright © 2011-2022 走看看