• 题意
    • 给一个长度为n的序列a,取出序列a每个长度大等于k的区间的第k大数放入序列b中,求序列b中的第m大值
    • n<1e5, a[i]<1e9
  • 题解
    • 我们容易用尺取法得出所有第k大数大于x的区间的个数
      • 具体如下
      • 用num计算当前区间中大于x的数的个数
      • if(num<k)
        • 那么移动右端点,并判断a[++r]>=x
          • 是则++num
      • else
        • 先判断num==k
          • 是则加上n-r+1
        • 再移动左端点,并判断a[l++]>=x
          • 是则–num
      • 重复上述操作,直至r>n
    • 我们发现,x越大,第k大数大于x的区间的个数越少,且b序列第m大数必定为a序列中的一个数
    • 所以我们可以将a序列排序,二分得到答案即可
  • 代码
    • m<=(n+1)*n/2,爆int
    • #include<algorithm>
      #include <iostream>
      #include  <fstream>
      #include  <cstdlib>
      #include  <cstring>
      #include  <cassert>
      #include   <cstdio>
      #include   <vector>
      #include   <string>
      #include    <cmath>
      #include    <queue>
      #include    <stack>
      #include      <set>
      #include      <map>
      using namespace std;
      #define P(a,b,c) make_pair(a,make_pair(b,c))
      #define rep(i,a,n) for (int i=a;i<=n;i++)
      #define per(i,a,n) for (int i=n;i>=a;i--)
      #define CLR(vis) memset(vis,0,sizeof(vis))
      #define MST(vis,pos) memset(vis,pos,sizeof(vis))
      #define pb push_back
      //#define mp make_pair
      #define all(x) (x).begin(),(x).end()
      #define fi first
      #define se second
      #define SZ(x) ((int)(x).size())
      typedef pair<int,pair<int,int> >pii;
      typedef long long ll;
      typedef unsigned long long ull;
      const ll mod = 1000000007;
      const ll INF = 1e18;
      ll gcd(ll a, ll b) {
      	return b ? gcd(b, a%b) : a;
      }
      template<class T>inline void gmax(T &A, T B) {
      	(A<B)&&(A=B);//if(B>A)A=B;
      }
      template<class T>inline void gmin(T &A, T B) {
      	(A>B)&&(A=B);//if(B<A)A=B;
      }
      template <class T>
      inline bool scan(T &ret) {
      	char c;
      	int sgn;
      	if(c=getchar(),c==EOF) return 0; //EOF
      	while(c!='-'&&(c<'0'||c>'9')) c=getchar();
      	sgn=(c=='-')?-1:1;
      	ret=(c=='-')?0:(c-'0');
      	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
      	ret*=sgn;
      	return 1;
      }
      inline void outt(int x) {
      	if(x>9) outt(x/10);
      	putchar(x%10+'0');
      }
      
      const int maxn = 1e5+10;
      int a[maxn];
      int b[maxn];
      
      ll n,k,m;
      bool check(int x){
      	int l = 1;
      	int r = 0;
      	int num = 0;
      	ll cnt = 0;
      	while(r<=n){
      		if(num<k){
      			if(a[++r] >= x)num++;
      		}else{
      			if(num==k) cnt += n-r+1;
      			if(a[l++] >= x)num--;
      		}
      	}
      	if(cnt<m)return false;
      	return true;
      }
      
      int main(){
      	int t;
      	scanf("%d", &t);
      	while(t--){
      		cin>>n>>k>>m;
      		rep(i,1,n){
      			scanf("%d", &a[i]);
      			b[i] = a[i];
      		}
      		sort(b+1,b+n+1);
      		int l = 1, r = n;
      		while(l<r){
      			int mid = (l+r+1)/2;
      			if(check(b[mid])){
      				l = mid;
      			}else{
      				r = mid-1;
      			}
      		}
      		cout<<b[l]<<endl;
      	}
      	return 0;
      } 

发表评论

邮箱地址不会被公开。 必填项已用*标注