20251020二分总结
引子
需要引子吗?
洛谷 P2249 【深基13.例1】查找
题目简化就是说给你n个单调不减的数,进行m次询问,每次询问给定一个数x,求x再这n个数当中最早出现的下标。
其实就是二分查找板子,只要套一下STL的二分查找函数就行了,或手搓二分查找;第二种做法就是用map充当桶数组。
在这里介绍一下二分查找函数:lower_bound以及upper_bound
其实都差不多,只不过lower_bound找的是序列里第一个大于等于这个数的下标,upper_bound找的是序列里第一个大于这个数的下标。
具体用法,()_bound(数组名+起始下标,数组名+结束下标,要找的数)-数组名
这道题用的肯定是lower_bound,首先用lower_bound查一遍要找的数,然后看找到的数跟要找的数是不是一样的。
时间复杂度O(mlogn)O(mlogn)O(mlogn)
#include<bits/stdc++.h>//二分查找写法
using namespace std;
int a[1000005];
int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];}while(m--){int x;cin>>x;int y=lower_bound(a+1,a+1+n,x)-a;//有函数为什么还要手搓?if(x!=a[y]){//如果找到的数不是一样的cout<<-1<<" ";}else{cout<<y<<" ";}}return 0;
}
map桶数组写法就是用一个map数组来记录每个数最早出现的下标,因为给的数组是单调不减的,所以只要看输入的数有没有被记录过,没记录过就更新就行了。
当然,还是因为给的数组是单调不减的,所以用unordered_map可以省那么一丢丢。
时间复杂度理想下O(n+m)O(n+m)O(n+m)
#include<bits/stdc++.h>//map桶数组写法
using namespace std;
unordered_map<int,int> t;
int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++){int x;cin>>x;if(!t[x]){//如果没记录过t[x]=i;}}while(m--){int x;cin>>x;if(!t[x]){//如果这个数没有出现过cout<<-1<<" ";}else{cout<<t[x]<<" ";}}return 0;
}
