K-th Number

传送门

题目大意:将A数组中所有区间第k大的数,放入B数组中,求B数组中第M大的数

思路:二分答案+尺取检验

暴力n^2铁tle

我们直接假设答案,验证假设的数是否是第M大

我们先转化一下题目所求,设x,我们去求x是B中第几大,即求A数组中大于等于x的数至少有k个的区间有多少个

举个例子A数组1,2,3,4 k=2   m=3 设x=2

我们去看x=2是B中第几大,即求A中至少有2个数大于等于2的区间有多少个,如果比m大,说明x小了,反之亦然(关于二分单调性,A中至少有2个数大于等于2的区间数,必定多于A中至少有2个数大于等于3的区间数,以此类推)

可以想,到最后若至少有2个数大于等于x的区间只有一个,那x必定是B中第一大的数,因为只有它满足,它肯定是最大的了

(这题二分还是很妙的)

再谈谈check怎么写

尺取检验,右指针j去找第一个满足至少有k个数大于x的位置,如果到n还找不到,就直接break了,找到了,那么对于j后面的所有位置都满足要求,直接答案累加 ans += n- j+1

所以左右指针都没必要左移,对于每个左指针i我们去找第一个满足要求的j即可

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(x,y) memset(x,y,sizeof(x))
#define all(v) v.begin() , v.end()
#define pb(v) push_back(v)
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define int long long
#define lson p*2,l,mid
#define rson p*2+1,mid+1,r
typedef long long ll;
const int N = 1e5+10;
int a[N];
int n,k,m;
bool check(int mid)
{
    int temp=0;
    ll ans=0;
    int j=1;
    int cnt=0;
    for(int i=1 ;i<=n ;i++)
    {
        while( cnt < k && j <= n)//找第一个满足有k个大于mid的区间
        {
             if( a[j]>=mid) cnt++;
             j++;
        }
        if( cnt < k )    break;//如果找不到对于左指针i的第一个匹配的右指针,break
        ans += n - (j-1) + 1;//找到的话,j后面所有的位置也必满足,直接累加
        if( a[i]>=mid ) cnt--;//左指针右移,看之前i的位置是否≥mid
    }
    return ans >= m;//如果区间数大于m说明mid小了
}
void solve()
{
    int l=1,r=1e9;
    ll ans=0;
    while( l<=r )
    {
        int mid = (l+r)>>1;
        if( check(mid) ) l=mid+1;
        else r=mid-1;
    }
    //l是mid的下界,即B数组中可能不止一个mid,l是mid的右区间
    //r是最后一个满足check的数
    cout<<r<<endl;
}
signed main()
{
    //!!!!!!!!!!!!!!!!!!!!!!
//    freopen("data.txt","r",stdin);
    //!!!!!!!!!!!!!!!!!!!!!!
    IOS;
    int T;
    cin>>T;
    while( T-- )
    {
        cin>>n>>k>>m;
        _for(i,1,n) cin>>a[i];
        solve();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sure, I understand your question. Based on the given conditions, Polycarp likes positive integers that are not divisible by 3 and do not end with the digit 3. We can generate this sequence of numbers as follows: 1, 2, 4, 5, 7, 8, 10, 11, 14, 16, 17, 19, 20, 22, 25, 28, 29, 40, 44, 46, 50, 52, 55, 58, 59, 70, 71, 74, 76, 79, 80, 82, 85, 88, 91, 94, 95, 97, 98, 100, 101, 104, 106, 107, 110, 112, 115, 118, 119, 121, ... To find the k-th element of this sequence, we can simply iterate through the sequence and stop at the k-th element. Here's the code to do that: ``` #include <iostream> #include <vector> using namespace std; bool is_disliked(int n) { return (n % 3 == 0) || (n % 10 == 3); } vector<int> generate_sequence(int n) { vector<int> seq; int i = 1; while (seq.size() < n) { if (!is_disliked(i)) { seq.push_back(i); } i++; } return seq; } int main() { int t; cin >> t; while (t--) { int k; cin >> k; vector<int> seq = generate_sequence(k); cout << seq[k-1] << endl; } return 0; } ``` The `is_disliked()` function checks if a number is disliked by Polycarp based on the given conditions. The `generate_sequence()` function generates the sequence of liked numbers by iterating through all positive integers and adding them to the sequence if they are not disliked. In the main function, we first read in the number of test cases `t`. Then we loop `t` times and for each test case, we read in the value of `k`, generate the sequence of liked numbers of length `k`, and output the k-th element of that sequence.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值