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了

posted @ 2026-03-26 10:51  Time_q  阅读(3)  评论(0)    收藏  举报