describe
Given n numbers, let the notation [l, r, t] denote the t-th largest value among the l-th to r-th numbers.
For given len, y and k, find the kth largest value in the multiset {[l,r,(r-l+1)/len*y] | (r-l+1) mod len=0}
Specifically, this multiset contains:
Each length is the y-th largest value in the interval of len,
Each length is the 2yth largest value in the interval of 2len,
Each length is the 3yth largest value in the interval of 3len,
……
And so on.
For the example below, the multiset is {2, 3, 3, 4}
enter
Four numbers in the first line, n, len, y, k (n ≤ 100000, y ≤ len ≤ n, k ≤ the number of intervals whose length is a multiple of len)
n in the second row, each number ≤ n
output
output a number to indicate the answer
4 2 1 3 2 1 3 4Sample output
3Ideas:
The binary answer ans
regards the original array greater than or equal to ans as len-y, and the less than ans as -y,
and then counts how many (length is a multiple of len) the sum of the interval is greater than or equal to 0, denoted as C
According to the size relationship between C and K, decide whether to divide the answer to the left or to the right.
You can use the prefix offset and tree array to count how many (length is a multiple of len) the sum of the interval is greater than or equal to 0.
#include<bits/stdc++.h> using namespace std; const int MAX=1e5+30; const int MOD=1e9+9; const double PI=acos(-1.0); typedef long long ll; int a[MAX],n,len,y; ll A[MAX],b[MAX],c[MAX],v[MAX]; void add(int x,int y) { while(x<=n+1) { A[x]+=y; x+=x&(-x); } } ll ask(int x) { ll ans=0; while(x) { ans+=A[x]; x-=x&(-x); } return ans; } ll check(int x) { for(int i=1;i<=n;i++) { b[i]=a[i]>=x?len-y:-y; b[i]+=b[i-1]; c[i]=b[i]; } c[n+1]=0; sort(c+1,c+n+2); int cd=unique(c+1,c+n+2)-c-1; for(int i=0;i<=n;i++)v[i]=lower_bound(c+1,c+cd+1,b[i])-c;//Discretize the value of the prefix sum for convenience insert tree array ll ans=0; for(int i=0;i<len;i++)//The prefix offset enumerates all intervals { add(v[i],1); for(int j=i+len;j<=n;j+=len) { ans+=ask(v[j]);//Count how many b[x]<=b[j] in the prefix and b[x] inserted before, that is, how many with j at the end of length len The interval sum is greater than or equal to 0. add(v[j],1); } add(v[i],-1);//Clear the tree array for(int j=i+len;j<=n;j+=len)add(v[j],-1); } return ans; } intmain() { ll k; cin>>n>>len>>y>>k; for(int i=1;i<=n;i++)scanf("%d",&a[i]); int l=-1e9,r=n,ans=0; while(r>=l) { int mid=(l+r)/2; if(check(mid)>=k) { ans=mid; l=mid+1; } else r=mid-1; } cout<<ans<<endl; return 0; }