atcoder 440 D
原文链接:https://www.cnblogs.com/Time25/p/19774670.html
题目
(https://atcoder.jp/contests/abc440/tasks/abc440_d)
大概的意思
给你一个数组,再给你几个问题,每个问题是一个x和一个y要求的是大于y的第x个数字是什么,这个数字不可以在这个数组中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using namespace std;
//"O campeão tem nome, e se chama Charles Oliveira!"
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在数组中,所以变成了阻碍,就要再加一
关键分析
原来二分还可以这样写??1
2
3
4
5
6
7
8
9
10
11
12
13
14while(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了
