三分法求最值简介

算法介绍

  • 算法简介:三分法适用于以O($logn$)复杂度求解单峰函数的最值,平均每次舍去$1/3$的定义域。
  • 适用条件:
    1. 有界性:有明确的初始定义域。
    2. 单峰性:仅存在一个目标最值,且最值两侧的函数单调。

(注:二分法用于求解单调函数零点,三分法用于求解单峰函数最值,二者思想相似,但适用条件有本质区别)

  • 实现细节:

    1. 确定初始区间$l,r$。
    2. 找到三等分点$m1,m2$,求出函数在这两点的函数值$f1,f2$。
    3. 比较$f1,f2$,将其中与最值方向相反的三等分点,所在的$1/3$定义域舍去。(详解见下,可配合画图理解)

模板分析

Deadline(CF1288A)

  • 题意:一个程序被要求在n天以内得出结果,但它实际得出结果却需要运行d天。你可以花费x天优化程序,使程序实际运行所需时间降为${d} \over {x+1}$(向上取整)。输入t组数据,判断能否在n天以内得出结果。
  • 分析:不考虑函数值的取整,实际花费总时间$f(x)=x+$ ${d} \over {x+1}$。由均值不等式可得,该函数为有最小值的单峰函数,可用三分法求出最小值。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
inline int get_min(int n,int d)
{
    double l=0,r=n,m1,m2,f1,f2;//有界性,0<=x<=n
    while(r-l>1e-2)
    {
        m1=l+(r-l)/3;
        m2=r-(r-l)/3;//求出三等分点
        f1=m1+d/(m1+1);
        f2=m2+d/(m2+1);
        if(f1>f2)l=m1;//*舍弃与最值方向相反的三等分点,所在的1/3区间
        else r=m2;
    }
    return min((int)l+ceil((double)d/((int)l+1)),ceil(l)+ceil((double)d/(ceil(l)+1)));//返回最小整数解
}
inline void solve()
{
    int n,d;
    scanf("%d %d",&n,&d);
    d=get_min(n,d);
    if(d<=n)printf("YES\n");
    else printf("NO\n");
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    solve();
    return 0;
}

原文地址:https://www.cnblogs.com/-SingerCoder/p/12422427.html

时间: 2024-10-08 22:59:57

三分法求最值简介的相关文章

hdu4521-小明系列问题——小明序列(线段树区间求最值)

题意:求最长上升序列的长度(LIS),但是要求相邻的两个数距离至少为d,数据范围较大,普通dp肯定TLE.线段树搞之就可以了,或者优化后的nlogn的dp. 代码为  线段树解法. 1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cct

杭电 1754 I Hate It(线段树求最值)

http://acm.hdu.edu.cn/showproblem.php?pid=1754 I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 38601    Accepted Submission(s): 15270 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某

poj3264(线段树区间求最值)

题目连接:http://poj.org/problem?id=3264 题意:给定Q(1<=Q<=200000)个数A1,A2,```,AQ,多次求任一区间Ai-Aj中最大数和最小数的差. 线段树功能:区间求最值,O(logN)复杂度查询 #pragma comment(linker,"/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <stri

CodeForces 444C 节点更新求变化值的和

http://vjudge.net/problem/viewProblem.action?id=51622 题目大意: 给定一列n个数字,最初赋予值1到n 两个操作:1.将区间[l,r]内的数改为x,则这区间中所有数的改变值进行求和,即ans=abs(a[l]-x)+abs[a[l+1]-x).....abs(a[r]-x),但不要求输出 2.需要将刚才要求得到的区间改变值输出出来 这里我们利用一个color[]数组相当于给这堆数进行染色,当某个区间内的赋予的值相等时,我们可以看做有一个相同的c

ACM3 求最值

/*2*2014.11.18*求最值*描述:给定N个整数(1<=N<=100),求出这N个数中的最大值,最小值.*输入:多组数据,第一行为一个整数N,第二行为N个不超过100的正整数,用空格隔开.*输出:对每组数据输出一行,包含两个整数,用一个空格隔开,分别表示N个数中的最大值和最小值*/ 1 #include <stdio.h> 2 const int N = 101; 3 int main() 4 { 5 int i,n,min,max; 6 int a[101]; 7 whi

python求crc32值的方法

python求crc32值的方法 在python代码中求CRC值,要import binasciibinascii.crc32(v) 求出了v的crc32值,这是一个long型,形如-1456387L,把这个值&0xffffffff得到的值形如48a213L的形式.然后,把这个值用16进制表示出来.www.jbxue.com例子: def _crc32(self, v): """ Generates the crc32 hash of the v. @return:

nyist 31 5个数求最值

5个数求最值时间限制:1000 ms | 内存限制:65535 KB 难度:1描述 设计一个从5个整数中取最小数和最大数的程序输入输入只有一组测试数据,为五个不大于1万的正整数输出输出两个数,第一个为这五个数中的最小值,第二个为这五个数中的最大值,两个数字以空格格开.样例输入1 2 3 4 5样例输出1 5 #include <iostream>using namespace std;int main ( ){ int i,max,min,a[5] ; for(i=0 ;i<5 ;i++

区间求最值 线段树

湖南师范大学 11460 区间求最值 区间求最值   Problem description   给定一个长度为N 的数组,有q个询问,每个询问是求在数组的一段区间内那个元素的因子的个数最大,比如24的因子的个数就是8.  Input   首先是一个整数t,表示有t组测试数据,每组测试数据的第一行是一个整数N(1<=N<=10^6),第二行有N个整数ai(1<=ai<=10^6,i=1,2,.....N)表示数组的元素.第三行有一个整数q(1<=q<=10^5),代表有

HDU - 1754 I Hate It (线段树区间求最值)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 题意:线段树的单点更新和区间求最值 模板题,,,???,, 1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 5 typedef long long LL; 6 const int N=200010; 7 8 LL ans; 9 LL max(LL a,LL b){ 10 if(a>b) r