二分与三分(提高篇)

这个星期忙着补笔记和写论文,在最近两天才看了看书,补了两道例题。

1433:【例题1】愤怒的牛

【题目描述】

农夫 John 建造了一座很长的畜栏,它包括N(2≤N≤100,000)个隔间,这些小隔间依次编号为x1,...,xN(0≤xi≤1,000,000,000). 但是,John的C(2≤C≤N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢

【输入】

第一行:空格分隔的两个整数NN和CC;

第二行---第N+1行:i+1行指出了xi的位置。

【输出】

一个整数,最大的最小值。

【输入样例】

5 3
1 2 8 4 9

【输出样例】

3

【提示】

把牛放在1,4,8这样最小距离是3。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define M 1000010
#define ll long long
#define Mid (l+r+1)/2
int l, r, mid;
int n, c;
int a[M];
inline bool check(int m) 
{
    int sum = a[1] + m;
    int cnt = 1;
    for(int i = 2; i <= n; i++) {
        if(a[i] >= sum) cnt++, sum = a[i] + m;
    }
    return cnt >= c;
}
int main() {
    scanf("%d%d", &n, &c);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    r = 10000000, l = 0;
    sort(a+1, a+n+1);
    while(l < r) {//二分答案
        mid = Mid;
        if(check(mid)) l = mid;
        else r = mid - 1;
    }
    printf("%d\n", l);
    return 0;
}

 

1434:【例题2】Best Cow Fences

【题目描述】

给定一个长度为n的正整数序列A。求一个平均数最大的,长度不小于L的子序列。

【输入】

第一行,n和L;

n个正整数,表示A。

【输出】

一个整数,表示答案的1000倍(不用四舍五入,直接输出)。

【输入样例】

10 6 
6 4 2 10 3 8 5 9 4 1

【输出样例】

6500

【提示】

n ≤ 100000

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define M 10000100
#define ex 1e-5
double l = 100000.0, r = -10000.0, mid;
int n, L;
double a[M], sum[M];
inline bool check(double ans)
{
    double sum1, sum2, maxx;
    sum1 = sum[L-1] - (L-1) * ans;
    for(int i = L; i <= n; i++) {
        sum2 = sum[i] - sum[i - L] - L * ans;
        sum1 = sum1 + a[i] - ans;
        sum1 = max(sum1, sum2);
        if(sum1 > -ex) return true;
    }
    return false;
}
 
int main() {
    scanf("%d%d", &n, &L);
    for(int i = 1; i <= n; i++) {
        scanf("%lf", &a[i]);
        sum[i] = sum[i-1] + a[i];
        l = min(l, a[i]), r = max(r, a[i]);
    }
    while(r - l > ex) {
        mid = (l + r)/2;
        if(check(mid)) l = mid;
        else r = mid;
    }
    int ans = (int)(r * 1000);
    printf("%d", ans);
    return 0;
}

1435:【例题3】曲线

【题目描述】

明明做作业的时候遇到了nn个二次函数Si(x)=ax2+bx+c,他突发奇想设计了一个新的函数F(x)=max(Si(x)), i=1,2...n。

明明现在想求这个函数在[0,10000,1000]的最小值,要求精确到小数点后四位四舍五入。

【输入】

输入包含TT 组数据 (T<10T<10) ,每组第一行一个整数 n(n≤10000) ,之后nn行,每行3个整数a(0≤a≤100),b(|b|≤5000),c(|c|≤5000),用来表示每个二次函数的3个系数,注意二次函数有可能退化成一次。

【输出】

每组数据一个输出,表示新函数F(x)的在区间[0,10000,1000]上的最小值。精确到小数点后四位,四舍五入。

【输入样例】

2
1
2 0 0
2
2 0 0
2 -4 2

【输出样例】

0.0000
0.5000

【提示】

【数据范围】

T<10,n≤10000,0≤a≤100,|b|≤5000,|c|≤5000T<10

前50%数据,n≤100。

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<algorithm>
#include<stack>
using namespace std;
#define ll long long
double cat[200001][3],sum[200001];
double a,b,c;
double Sx(double x,int  n)
{
    double k=-1e10;
    for(int i=1;i<=n;i++)
        k=max(k,cat[i][0]*x*x+cat[i][1]*x+cat[i][2]);
    return k;
}
int main()
{
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    while(n--)
    {
        int gr;
        cin>>gr;
    double l=0,r=1000,exp=1e-11;
    for(int i=1;i<=gr;i++)
    for(int j=0;j<3;j++)
        cin>>cat[i][j];
    while(r-l>exp)
    {
        double mid=(l+r)/2;
        double midmid=(mid+r)/2;
        if(Sx(mid,gr)>=Sx(midmid,gr))l=mid;
        else r=midmid;
    }
    cout<<fixed<<setprecision(4)<<Sx(r,gr)<<endl;
    }
}

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值