CF924B Three-level Laser 题解

题目传送门~

题目分析

主要思路:枚举每个 $i$,求出对应最佳情况的 $j$ 和 $k$,取最大值。

  • 当 $i$,$k$ 固定时,显然 $E_k-E_i$ 为定值。此时 $E_k-E_j$ 应取最大值,即 $E_j$ 取最小值,$j$ 应取最小值为 $i+1$。

  • 当 $i$,$j$ 固定时,$\frac{E_k-E_j}{E_k-E_i} $ 取最大值当且仅当 $E_k$ 取得最大值且 $E_k - E_i \le U$。具体证明见下。这一步可以用二分解决。

证明:$\frac{E_k-E_j}{E_k-E_i} $ 取最大值当且仅当 $E_k$ 取得最大值。

假设存在 $E_{k_1} < E_{k_2},x = E_{k_2} - E_{k_1}$ 使得:

$$\frac{E_{k_1}-E_j}{E_{k_1}-E_i} > \frac{E_{k_2}-E_j}{E_{k_2}-E_i} $$

换元简化式子可得:

$$\frac{a}{b} > \frac{a+x}{b+x} (a > 0,b>0,x>0) $$ 进一步化简得:$$a > b$$ 显然矛盾,故假设不成立,原命题成立。

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+5;
int n,k,a[N];
double res = -1;

int find(int i)
{
    int x = a[i]+k,l = i+2,r = n;   
    while (l < r) // 二分
    {
        int mid = l + r + 1 >> 1;
        if (a[mid] <= x) l = mid;
        else r = mid-1;
    }
    if (a[l] <= x) return l;
    else return -1;
}

int main()
{
    scanf("%d%d",&n,&k);
    for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
    for (int i = 1;i <= n-2;i++)
    {
        int x = find(i);
        if (x == -1) continue; // i j k 分别为 i i+1 x
        res = max(res,1.0*(a[x]-a[i+1])/(a[x]-a[i]));   
    }
    if (res < 0) puts("-1"); //不存在
    else printf("%.10f",res);
    return 0;
}
posted @ 2023-10-27 10:59  codwarm  阅读(13)  评论(0)    收藏  举报  来源