atcoder 440 D
题目
(https://atcoder.jp/contests/abc440/tasks/abc440_d)
大概的意思
给你一个数组,再给你几个问题,每个问题是一个x和一个y要求的是大于y的第x个数字是什么,这个数字不可以在这个数组中
#include<bits/stdc++.h>
using namespace std;
//"O campeão tem nome, e se chama Charles Oliveira!"
#define int long long
#define endl '\n'
#define ep emplace
#define pob
#define ll long long
#define pb push_back
#define pof pop_front
#define pob pop_back
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define mod 998244353
#define MOD 1000000007
const int N=200005;
using ld = long double;
using ui = unsigned;
using ull = unsigned long long;
using i128 = __int128;
void solve() {
int n,q;cin>>n>>q;
vector<int>num(n+1);
for(int i=1;i<=n;i++){
cin>>num[i];
}
//记得用下面这个二分的时候,这个数组要是从0下标开始的,如果一定要从1下标开始的话,记得r要换成n+1,因为这个r是要越界的
sort(num.begin(),num.end());
while(q--){
int x,y;cin>>x>>y;
int be=lower_bound(all(num),x)-num.begin();
int l=be-1,r=n+1;
while(l+1<r){
int med=(l+r)/2;
if((num[med]-x+1)-(med-be+1)>=y){
r=med;
}else{
l=med;
}
}
cout<<x+(y-1)+(l-be+1)<<endl;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t=1;
//cin>>t;
while(t--)solve();
}
代码解析
就是求出这个数组中第一个大于等于x的数字,然后看这个数组中有多少个是阻碍的,只要用x+(y-1)然后再加上那几个在数组中的数字
比如x=6,y=10
数组是[16 9 2 3 1]
那么就是10+6+1=17,因为本来是16的,但是16在数组中,所以变成了阻碍,就要再加一
关键分析
原来二分还可以这样写??
while(q--){
int x,y;cin>>x>>y;
int be=lower_bound(all(num),x)-num.begin();
int l=be-1,r=n+1;
while(l+1<r){
int med=(l+r)/2;
if((num[med]-x+1)-(med-be+1)>=y){
r=med;
}else{
l=med;
}
}
cout<<x+(y-1)+(l-be+1)<<endl;
}
这样的二分好像可以处理一些极端的情况,好耶,而且也不必去考虑什么到底是左边还是右边+1,-1了

浙公网安备 33010602011771号