2024.6.3练习情况—整数二分

2024.6.3练习情况—整数二分

一、洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树

  1. 题目

  1. 分析

参考题解完成。在这个题中数据量很大,是10的9次方,要考虑开longlong。单纯用暴力使用for循环的话肯定是要暴空间和时间的,所以要考虑优化使用二分。

题中要求所有树的高度总和 > M,也就是说不可能要求将树全部砍到。这是我们可以确定二分的左右边界是所给出树高度的最大值和最小值。分别用minn和maxx记录。

这个题要求锯片的最高高度也就是要求给出能满足要求的最大值。这里思考的是使用求右端点的二分模板,并在if判断语句里再使用check函数。在check函数里判断当前值mid是否满足条件,即sum+=(arr[i]-mid)是否大于等于m如果check函数返回true,则说明设置的锯片高度低了,需要将l=mid

代码

#include<iostream>

#include<algorithm>

using namespace std;

const int N = 1000010;

int n;

long long m;

int arr[N];

long long sum;

bool check(int arr[],int mid){

        sum=0;

        for(int i=0;i<n;i++){

                if(arr[i]>mid){

                        sum+=(arr[i]-mid);

                }

        }

        if(sum>=m) return true;

        else return false;

}

int main()

{

        cin>>n>>m;

        for(int i=0;i<n;i++){

                cin>>arr[i];

        }

        sort(arr,arr+n);

       

        int maxx=arr[n-1];

        int minn=arr[0];

       

        int l=minn,r=maxx;

       while(l<r){

              int mid=(l+r+1)/2;

              if(check(arr,mid)) l=mid;

              else r=mid-1;

       }

        cout<<l<<endl;      

        return 0;

}

  1. 运行评判结果

三、复习洛谷P1102 A-B 数对

  1. 题目

  1. 分析

完全独立完成。针对练习的算法整数二分加上昨天学习题解的方法对这个题进行思考,因为题中说每个位置都算不同的结果,所以可以使用for循环将每个位置b加上c找到对应的A,并在数列中找到A的左右端的编号ll和rr。将每个位置找到的(rr-ll+1)相加就是最后结果。注意使用这种方法时要先将数列排序

  1. 代码

代码:

#include<iostream>

#include<algorithm>

using namespace std;

const int N = 200010;

int n,c;

long long ans;

int arr[N];

//找左端,左端大右

int findleft(int arr[],int k){

        int l=0,r=n-1;

        while(l<r){

                int mid=(l+r)/2;

                if(arr[mid]>=k){

                        r=mid;

                }

                else l=mid+1;

        }

        if(arr[l]==k){

                return l;

        }

        return -1;

}

//找右端,右端小左

int findright(int arr[],int k){

        int l=0,r=n-1;

        while(l<r){

                int mid=(l+r+1)/2;

                if(arr[mid]<=k){

                        l=mid;

                }

                else r=mid-1;

        }

        if(arr[l]==k){

                return l;

        }

        else return -1;

}

int main()

{

        cin>>n>>c;

        for(int i=0;i<n;i++){

                cin>>arr[i];

        }

        //要先对数列排序

        sort(arr,arr+n);

        //因为每个位置都算不同的结果

        for(int i=0;i<n;i++){

                int temp=arr[i]+c;

                int ll=findleft(arr,temp);

                if(ll==-1) continue;

                else{

                        int rr=findright(arr,temp);

                        ans+=(rr-ll+1);

                }

        }

        cout<<ans<<endl;

        return 0;

 }

  1. 运行评判结果

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值