洛谷——《二分查找和二分答案》

文章介绍了几个C++编程题目,涉及二分查找、排序、贪心策略等技术,包括数组操作、区间查找、满足条件的最大值或最小值计算等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// #include<iostream>
// #include<iomanip>
// #include<cmath>
// #include<string.h>
// #include<string>
// #include <ctime>
// #include<cstdlib>
// #include<algorithm>
// #include<cstdio>
// using namespace std;

#include<iostream>
#include<iomanip>
#include<cmath>
#include<string.h>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
using namespace std;

//p2249
// long long arr[1000000];
// long long n,m,q;

// long long find(long long x)
// {
//     long long left = 1,right = n;
//     while(left<right)
//     {
//         long long mid = (left+right)/2;
//         if(arr[mid]<x)left = mid+1;
//         else right = mid;
//     }
//     if(arr[left]==x)return left;
//     return -1;
// }
// int main()
// {
//     cin>>n>>m;
//     for(int i =1;i<=n;i++)cin>>arr[i];
//     for(int i =0;i<m;i++)
//     {
//         cin>>q;
//         long long result = find(q); 
//         cout<<result<<' ';
//     }
// }

//p1102
// 1.a = b+c
// 2.排序枚举所有a,二分找到对应的b+c区间
// long long arr[1000000];
// long long n,ans,c;
// 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++)
//     {
//         ans+=upper_bound(arr,arr+n,arr[i]+c)-lower_bound(arr,arr+n,arr[i]+c);
//     }
//     cout<<ans;
// }


// p1873
// 1.判断高度为x是否可以达到木材需要
// 2.通过二分来遍历获得最大高度

// long long arr[10000000];
// long long n,m,ans;
// long long maxi =0;

// bool is_get(int high)
// {
//     long long sum =0;
//     for(int i =0;i<n;i++)
//     {
//         if(arr[i]>high)sum+=arr[i]-high;
//     }
//     if(sum>=m)return 1;
//     else return 0;
// }

// long long find()
// {
//     long long left = 0, right =maxi;
//     while (left<right)
//     {
//         long long mid = (left+right+1)/2;
//         if(is_get(mid))
//         {
//             left =mid;
//         }
//         else 
//         {
//             right = mid-1;
//         }
//     }
//     return left;
// }
// int main()
// {
//     cin>>n>>m;
//     for(int i =0;i<n;i++)
//     {
//         cin>>arr[i];
//         if(arr[i]>maxi)maxi = arr[i];
//     }
//     ans = find();
//     cout<<ans;

// }


//1024

// double ans,eps = 1e-4;
// double a,b,c,d;

// double f(double x)
// {
//     double res = a*x*x*x+b*x*x+c*x+d;
//     return res;
// }
// int main()
// {
//     cin>>a>>b>>c>>d;
//     for(int i =-100;i<=100;i++)
//     {
//         double left = i,right = i+1,mid;
//         if(fabs(f(left))<eps)
//             cout<<fixed<<setprecision(2)<<left<<' ';
//         else if(fabs(f(right))<eps)continue;
//         else if(f(left)*f(right)<0)
//         {
//             while((right-left)>eps)
//             {
//                 mid = (right + left)/2;
//                 if(f(mid)*f(right)>0)right = mid;
//                 else left = mid;
//             }
//             cout<<fixed<<setprecision(2)<<left<<' ';
//         }
//     }
    
// }


//p1678
//函数输入分数获得最小不满
// int arr[100000];
// int n,m;
// long long ans;
// int min(int x)
// {
//     int left = 0,right = n-1;
//     while(left<right)
//     {
//         long long mid = (left+right+1)/2;
//         if(arr[mid]<=x)
//         {
//             left = mid;
//         }
//         else right = mid-1;
//     }
//     return abs(arr[left]-x)<abs(arr[left+1]-x)?abs(arr[left]-x):abs(arr[left+1]-x);
// }
// int main()
// {
//     cin>>n>>m;
//     int item;
//     for(int i =0;i<n;i++)cin>>arr[i];
//     sort(arr,arr+n);
//     for(int i =0;i<m;i++)
//     {
//         cin>>item;
//         ans +=min(item);
//     }
//     cout<<ans;
// }


//p2240
//我直接判断是贪心
// 1.先从小到大排序
// 2.函数输入木头长度判断是否大于k
// 3.二分找到长度的最大值

// long long arr[10000000];
// long long n,k;
// bool is_k(long long len)
// {
//     long long ans= 0;
//     for(int i= 0;i<n;i++)
//     {
//         ans +=arr[i]/len;
//     }
//     return ans>=k;
// }
// int main()
// {
    
//     cin>>n>>k;
//     for(int i = 0;i<n;i++)cin>>arr[i];
//     sort(arr,arr+n);
//     long long left =0,right =0xffffffff;
//     while (left<right)
//     {
//         long long mid = (left+right+1)/2;
//         if(is_k(mid))
//         {
//             left = mid;
//         }
//         else right = mid-1;
//     }
//     cout<<left;

// }

// p2678
// 1.求最短距离的最大
// 2.找到一个和两边距离最小的石头,删掉它
// 3。函数输入距离判断要删掉多少石头
// 4.二分找到距离的最大值

// long long arr[1000000];
// long long b[1000000];

// long long l,n,m;

// bool is_m(long long dis)
// {
//     long long count =0;
//     for(int i =1;i<=n+1;i++)b[i] = arr[i];
//     for(int i =1;i<=n+1;i++)
//     {
//         if(b[i]-b[i-1]<dis)
//         {
//             b[i] = b[i-1];
//             count++;
//         }
//     }
//     return count<=m;
// }
// int main()
// {
//     cin>>l>>n>>m;
//     for(int i =1;i<=n;i++)cin>>arr[i];
//     arr[n+1] = l;
//     long long left = 1,right = 0xffffffff;
//     while (left<right)
//     {
//         long long mid = (left+right+1)/2;
//         if(is_m(mid))
//             left = mid;
//         else  right = mid-1;
//     }
//     cout<<left;
   
// }

// p3853
// 1.空旷指数在长度范围内,可以二分找到
// 2.空旷指数越大,设置路标数量越少
// 3.函数输入空旷指数,判断路标数量是否够少

// long long arr[1000000];
// long long b[1000000];

// long long n,k,l;
// bool is_k(long long len)
// {
//     long long ans =0;
//     for(int i =1;i<n;i++)
//     {
        
//         ans +=b[i]/len;
//         if(b[i]%len==0)ans--;
//     }
//     return ans<=k;
// }
// int main()
// {
//     cin>>l>>n>>k;
//     for(int i =0;i<n;i++)cin>>arr[i];
//     for(int i =1;i<n;i++)b[i] = arr[i]-arr[i-1];
//     long long left = 1,right = 0xffffffff;
//     while (left<right)
//     {
//         long long mid = (left+right)/2;
//         if(is_k(mid))
//             right = mid;
//         else  left = mid +1;
//     }
//     cout<<left;
// }

// p1182
// 1.最大值的最小在和的范围内,可以二分
// 2.趋势:最大值越大,划分的次数就越少
// 3.函数:输入最大值,小于等于划分次数
// (有一个点不知道错哪了)
// long long arr[10000000];
// long long n,m;
// bool is_m(long long len)
// {
//     int ans = 0;
//     long long sum =0;
//     for(long long i =0;i<n-1;i++)
//     {
//         sum+=arr[i];
//         if(sum+arr[i+1]>len)
//         {
//             sum =0;
//             ans++;
//         }
//     }
//     ans++;
//     return ans<=m;
// }
// int main()
// {
//     cin>>n>>m;
//     for(long long i =0;i<n;i++)cin>>arr[i];
//     long long left = 1,right = 0xffffffff;
//     while (left<right)
//     {
//         long long mid = (left+right)/2;
//         if(is_m(mid))
//             right = mid;
//         else  left = mid +1;
//     }
//     cout<<left;
// }

// p1163

### 关于洛谷平台上的二分查找 Python 题目及其解法 #### 一、题目背景与描述 在洛谷平台上,涉及二分查找的题目通常会提供一个有序数组作为输入数据,并要求通过高效的方式完成特定查询操作。例如,在引用中的 P2249 题目中提到的任务是基于给定的一个单调不降序列以及多次询问来定位目标值首次出现的位置[^4]。 此类问题的核心在于利用已知条件——即数组已经按照升序排列这一特性,从而采用更高效的搜索策略代替简单的线性扫描方法。具体来说,当面对长度较大的列表时(如 \(n \leq 10^6\)),传统遍历方式的时间复杂度较高 (\(O(n)\)),而借助二分查找则可显著降低至 \(O(\log n)\)[^2]。 #### 二、标准实现方案 以下是针对上述需求的一种典型解决方案: ```python import sys from bisect import bisect_left def solve(): input_data = sys.stdin.read() data = list(map(int, input_data.split())) # 获取初始参数 index = 0 n = data[index]; index += 1 array = data[index:index+n]; index += n m = data[index]; index += 1 queries = data[index:] result = [] for q in queries: pos = bisect_left(array, q) # 使用内置函数寻找左侧边界 if pos != len(array) and array[pos] == q: result.append(pos + 1) # 转换为从1开始计数的形式 else: result.append(-1) print(' '.join(map(str,result))) solve() ``` 此代码片段展示了如何运用 `bisect` 库简化编程过程并提高效率。其中的关键点包括但不限于以下几个方面: - **读取大容量输入**:考虑到可能存在的大量数据项,推荐直接一次性加载整个文件流而非逐行处理。 - **应用现成工具**:相比手动编码二分逻辑,调用经过优化的标准库往往更加可靠且易于维护。 - **注意细节调整**:由于某些场合下索引是从零还是从一开始有所不同,因此需适当转换最终输出结果[^1]。 #### 三、扩展思考方向 除了基本形式外,还有许多变种情形值得探索。比如下面列举的一些延伸话题可以帮助进一步加深理解程度:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值