寒假笔记·二分法与滚动数组

二分法

当题目可能需要多个for循环叠加时,可以使用二分法来减少运算量。二分法的主要难点在编写check函数上。

例题:P1824 进击的奶牛

原题地址
题目描述

Farmer John建造了一个有N(2<=N<=100,000)个隔间的牛棚,这些隔间分布在一条直线上,坐标是x1,…,xN (0<=xi<=1,000,000,000)。

他的C(2<=C<=N)头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?

输入输出格式

输入格式:
第1行:两个用空格隔开的数字N和C。

第2~N+1行:每行一个整数,表示每个隔间的坐标。

输出格式:
输出只有一行,即相邻两头牛最大的最近距离。

输入输出样例

输入样例#1:
5 3
1
2
8
4
9

输出样例#1:
3
代码:

扫描二维码关注公众号,回复: 5540891 查看本文章
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int qq[100010];
int r,l,n,m,mid;
int jug(int x)
{
    int i,le,cnt=1;
    le=qq[1];
    for(i=2;i<=n;i++)
    {
        if(qq[i]-le>=x)
        {
            cnt++;
            le=qq[i];
        }
        if(cnt>=m) break;
    }
    return cnt>=m;
}
int main()
{
    int i;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        scanf("%d",&qq[i]);
    sort(qq+1,qq+n+1);
    l=1;
    r=qq[n]-qq[1];
    while(l<r-1)//二分法部分
    {
        mid=(l+r+1)/2;
        if(jug(mid)) l=mid;
        else r=mid;
    }
    if(jug(r)) printf("%d\n",r);
    else printf("%d\n",l);
    return 0;
}

例题:P1843 奶牛晒衣服

原题地址

题目描述

熊大妈请你帮助完成这个重任 。 洗完衣服后 , 你就要弄干衣服 。 衣服在

自然条件下用 1 的时间可以晒干 A 点湿度 。 抠门的熊大妈买了 1 台烘衣机 。

使用烘衣机可以让你用 1 的时间使 1 件衣服除了自然晒干 A 点湿度外,还

可以烘干 B 点湿度,但在 1 的时间内只能对 1 件衣服使用。

N 件衣服因为种种原因而不一样湿 , 现在告诉你每件衣服的湿度 , 要你

求出弄干所有衣服的最少时间(湿度为 0 为干 ) 。

输入输出格式

输入格式:
第一行 N , A , B ;接下来 N 行,每行一个数,表示衣服的湿度( 1 ≤ 湿度, A , B ≤ 500000 , 1 ≤ N ≤ 500000 ) 。

输出格式:
一行,弄干所有衣服的最少时间。

输入输出样例

输入样例#1:
3 2 1
1
2
3
输出样例#1:
1

代码:

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,a,b;
int qq[500050];
bool check(int x)
{
    int k,y,i,j;
    k=0;
    for(i=1;i<=n;i++)
    {
        j=qq[i]-a*x;
        if(j<=0) continue;
        y=j/b;
        if(j%b) y++;
        k+=y;
        if(k>x) return 0;
    }
    if(k<=x) return 1;
    else return 0;
}

int main()
{
    int i,le,ri,mid,ans;
    scanf("%d%d%d",&n,&a,&b);
    for(i=1;i<=n;i++)
        scanf("%d",&qq[i]);
    sort(qq+1,qq+1+n);
    le=qq[1]/a;
    if(qq[1]%a) le++;
    ri=qq[n]/a;
    if(qq[n]%a) ri++;
    while(le+1<ri)//二分部分
    {
        mid=(le+ri+1)/2;
        if(check(mid)) ri=mid;
        else le=mid;
    }
    if(check(le)) ans=le;
    else ans=ri;
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43918350/article/details/87969976