首页 > 其他分享 >从CF1730B看题意转化与二分三分

从CF1730B看题意转化与二分三分

时间:2024-03-12 17:47:05浏览次数:21  
标签:二分 std max 题意 int double m1 m2 CF1730B

Problem - 1730B - Codeforces

贪心解法

\(∣a−b∣=\max(a−b,b−a)\)

由绝对值的性质易证。

那么直接把 \(t_i\) 算到距离中,转换成求最左和最右“坐标”的中间点的简单问题。

//通过把t[i]算到距离中,转换成求最左和最右坐标的中间点的简单情况

void solve()
{
    #define tests
    int n;
    std::cin >> n;

    std::vector<int> x(n), t(n);
    for (int i = 0; i < n; i++) std::cin >> x[i];
    for (int i = 0; i < n; i++) std::cin >> t[i];

    std::vector<int> a;
    for (int i = 0; i < n; i++) {
        a.push_back(x[i] + t[i]);
        a.push_back(x[i] - t[i]);
    }

    int mn = a[0], mx = a[0];
    for (int val : a) {
        mn = std::min(mn, val);
        mx = std::max(mx, val);
    }

    int sum = mn + mx;
    std::cout << sum / 2;
    if (sum % 2 != 0)
        std::cout << ".5";
    std::cout << '\n';
}

二分解法

对 \(x_0\) 进行二分,判断左边和右边谁到达 \(x_0\) 的最大时间更大

如果左边距离更大,就往左边靠近继续二分

void solve() {
    #define tests
    int n;
    scanf("%d", &n);
    
    std::vector<i64> a(n);
    std::vector<i64> t(n);

    for (auto& x : a) scanf("%d", &x);
    for (auto& x : t) scanf("%d", &x);
    
    double lo(0), hi(*std::max_element(all(a))); 
    
    int res(0);

    auto check = [&](auto X) -> bool {
        double lMax(0), rMax(0);
        for (int i = 0; i < n; i++) {
            if (a[i] < X) {
                lMax = std::max(lMax, X - a[i] + t[i]);
            }
            else {
                rMax = std::max(rMax, a[i] - X + t[i]);
            }
        } 
        return rMax < lMax;
    };

    constexpr double eps(1E-7);

    while(hi - lo > eps) {
        double mid((lo + hi) / 2.0);
        if (check(mid)) {
            hi = mid;
        }
        else {
            lo = mid;
        }
    }

    printf("%.6lf\n", hi);
}

三分解法

三分法适用于给出 \(N\) 个函数,保证在范围内存在一点 \(x\),使得左边界 \(x\) 上单调增,\(x\) 到右边界上单调减。

可以用三分求出 \(\max(f_1(x), f_2(x), f_3(x), \dots, f_n(x))\) 取最小时,对应的 \(x\) 的值。

而这题的绝对值函数 \(T_i = t_i + \left | x_i - x_0 \right |\) 满足条件,所以直接对 \(x_0\) 进行三分。

int _, n, a[N], t[N];

double f(double x, LL i) {
    return (fabs(a[i] - x) + t[i]);
}

double check(double x) {
    double res = f(x, 1);
    for (int i = 2; i <= n; i++) {
        res = max(res, f(x, i));
    }
    return res;
}

void solve() {
    cin >> n;
    for (LL i = 1; i <= n; i++) cin >> a[i];
    for (LL i = 1; i <= n; i++) cin >> t[i];
    double m1, m2, l = 0, r = 0x3f3f3f3f;
    while (r - l > eps) {
        m1 = l + (r - l) / 3.0;
        m2 = r - (r - l) / 3.0;
        if (check(m1) > check(m2)) {
            l = m1;
            // 如果m1对应的函数最大值比m2对应的值要大。
            // 则说明左边界l需要收敛
        }
        else {
            r = m2;
            // 如果m2对应的函数最大值比m1对应的值要大。
            // 则说明右边界r需要收敛
        }
    }
    printf("%.7lf\n", l);
}

标签:二分,std,max,题意,int,double,m1,m2,CF1730B
From: https://www.cnblogs.com/kdlyh/p/18068836

相关文章

  • 取反(分块+二分)
    第2题   取反 查看测评数据信息给一个长度是n的数组,a[1],a[2],a[3],...a[n-1],a[n],初始时a数组中所有的元素都为0,下面有两种操作:1.指定一个区间[x,y],把a[x],a[x+1],...a[y]的值取反,即如果a[i]的值为1则把a[i]的值变为0,如果a[i]的值为0则把a[i]的值变为12.指定一个区......
  • 统计数量(分块+二分)
    第1题   统计数量 查看测评数据信息给一个长度是n的正整数数组,a[1],a[2],a[3],...a[n-1],a[n],其中1<=a[i]<=1000。现在在数组a上进行m次操作:1.Mxyz,表示对a数组的闭区间[x,y]内所有a[i]的值分别加上z2.Axyzz,询问a数组闭区间[x,y]内有多少a[i]的值大于等于z......
  • POJ--3258 River Hopscotch(二分搜索/最大化最小值)
    记录10:232023-3-11http://poj.org/problem?id=3259二分法查找最大的可能解,检查x是否符合条件(当前这个位置上的值-前上一个选取位置的值>=x)注意的点:使用了[begin,end)的左闭右开区间,所以结果要begin-1,end要从L+1开始算点击查看代码intL,N,M;introcks[5......
  • 蓝桥杯算法集训 - Week1:二分、前缀和、差分算法
    蓝桥杯算法集训-Week1本系列随笔用于整理AcWing题单——《蓝桥杯集训·每日一题2024》的系列题型及其对应的算法模板。一、二分查找二分算法原理复习参考:二分查找-Hello算法Ⅰ、二分模板boolcheck(intx){/*...*/}//检查x是否满足某种性质//区间[l,r]被划分......
  • 第一节二分
    第一节:二分定义:(一遍恒比这个值小一遍恒比这个值大为了找出这个值第一次或最后一次出现的位置所以用二分)注意,这里的有序是广义的有序,如果一个数组中的左侧或者右侧都满足某一种条件,而另一侧都不满足这种条件,也可以看作是一种有序(如果把满足条件看做 ,不满足看做 ,至少对于这个条......
  • 二分搜索模板
    目录最基本的二分搜索寻找左边界的二分搜索寻找右边界的二分搜索统一记忆为闭区间,只需要修改nums[mid]==target时收缩哪边边界,以及越界情况最基本的二分搜索defbinary_search(nums:List[int],target:int):left=0right=len(nums)-1while(left<=right):......
  • 代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。
    704.二分查找https://leetcode.cn/problems/binary-search/description/一、左闭右闭`//左闭右闭publicstaticinterFen1(int[]nums,inttarget){if(target<nums[0]||target>nums[nums.length-1]){return-1;}intmaxIndex=nums.length-......
  • 洛谷题单指南-二分查找与二分答案-P3743 kotori的设备
    原题链接:https://www.luogu.com.cn/problem/P3743题意解读:设备使用的时间越久,需要充电的总时间也越多,具备单调性,根据使用的时间,计算需要充电的时间,如果充电总时间<=使用的时间,说明有电量还能富余,使用时间还可以更多,因此只需对使用时间进行二分即可。解题思路:给定设备使用的时间......
  • 洛谷题单指南-二分查找与二分答案-P1163 银行贷款
    原题链接:https://www.luogu.com.cn/problem/P1163题意解读:利率越小,贷款期限和每个月还的钱固定的情况下,越有可能能够还完全部的贷款,具备单调性,因此给定贷款利率、贷款月数、每月还款钱数,可以计算最终贷款还剩下多少,有两种情况:>=0,说明利率可能大了,要试探更小利率;<0,说明利率小了,要......
  • 【基础算法】二分查找
    二分查找什么是二分?将问题分成两个部分。猜数游戏计算机给你一个范围内的随机数,你要输入一个数,计算机给你反馈是太大了还是太小了,直到你输出正确的答案。怎么设计这个程序呢?#include<iostream>#include<ctime>usingnamespacestd;intmain(){srand(time(NULL));......