HELLO WORLD--一起加油(🍺)!|

kingwzun

园龄:3年6个月粉丝:111关注:0

2022-11-04 21:58阅读: 46评论: 0推荐: 0

B - K-th Number HDU - 6231 (二分 尺取)

WindowsSource 2017中国大学生程序设计竞赛-哈尔滨站

题意

给一个数组,在所有长度大于等于k的区间内,找出第 k 大的数,放到另一个数组中,然后在新数组中找到第M大的数。

思路

二分答案,每次二分的时候我们得到一个x
对于每个x 利用尺取,得到 第K大的数大于等于x 的区间一共有多少个

原文1
原文2

代码1

二分下标

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
const int mod = 1e9+7;
int a[N];
int b[N];
int n,k,m;
//求 第K大的数大于等于x 的区间一共有多少个
int check(int x){
int ans=0;
int num=0;//j-i之间 大于x的数 的数量
int j=1;
for(int i=1;i<=n;i++){
if(a[i]>=x) num++;
if(num==k){
ans+=n-i+1;
while(a[j]<x){
ans+=n-i+1;
j++;
}
num--,j++;
}
}
return ans;
}
void solve(){
cin>>n>>k>>m;
for(int i=1;i<=n;i++)
cin>>a[i] , b[i]=a[i];
sort(b+1,b+n+1);
int l=1,r=n;
int ans=0;
while(l<=r){
int mid=l+r>>1;
int x=check(b[mid]);
if(x==m){
ans=mid;
break;
}
else if(x>m){
ans=mid;
l=mid+1;
}
else r=mid-1;
}
cout<<b[ans]<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--) solve();
return 0;
}

代码2

也可以 直接二分数

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int N,K;
ll M;
int a[100005];
bool judge(int x){
ll ans = 0;
int num = 0;
int j = 1;
for(int i = 1; i <= N; i++){
if(a[i] >= x)
num++;
if(num == K){
ans += N - i + 1;
while(a[j] < x){
ans += N - i + 1;
j++;
}
num--;
j++;
}
}
if(ans >= M)
return true;
else
return false;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%lld",&N,&K,&M);
for(int i = 1; i <= N; i++){
scanf("%d",&a[i]);
}
int l = 1,r = 1000000000;
int m;
while(l < r){
m = l + r >> 1;
if(judge(m))
l = m + 1;
else
r = m;
}
printf("%d\n",l-1);
}
return 0;
}

本文作者:kingwzun

本文链接:https://www.cnblogs.com/kingwz/p/16859254.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   kingwzun  阅读(46)  评论(0编辑  收藏  举报
历史上的今天:
2021-11-04 xxxx
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起