题意:中文
思路:之前看了好久感觉应该二分答案,但是二分条件不会写,看了出题人的题解恍然大悟,对于二分的mid,统计到i为止的大于等于mid的个数,然后若一段区间的中位数大于等于mid的话,则2*(num[r]-num[l-1]>r-l+1;代表这个区间的大于等于mid的个数比区间一半的元素多,则中位数就大于等于md,转化一下就是2*num[r]-r>2*num[l-1]-l+1;所以我们设另一个数组为2*num[i]-i;则对于每一个i,统计小于它的j的个数即可
#include <queue>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
int num[maxn],sum[maxn<<1],n,a[4*maxn],b[4*maxn];
ll k;
int lowbit(int x){return x&(-x);}
void modify(int x,int add,int c[]){
while(x<2*maxn){
c[x]+=add;
x+=lowbit(x);
}
}
int get_sum(int x,int c[]){
int ret=0;
while(x!=0){
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
int judge(int mid){
sum[0]=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++){
if(num[i]>=mid) sum[i]=sum[i-1]+1;
else sum[i]=sum[i-1];
}
for(int i=1;i<=n;i++) sum[i]=2*sum[i]-i+maxn;
ll ans=0;
modify(maxn,1,b);
for(int i=1;i<=n;i++){
if(i%2==0){
modify(sum[i],1,b);
ans+=(ll)get_sum(sum[i]-1,a);
}
else{
modify(sum[i],1,a);
ans+=(ll)get_sum(sum[i]-1,b);
}
}
return ans>=k;
}
int main(){
while(scanf("%d%I64d",&n,&k)!=-1){
int max1=0;
for(int i=1;i<=n;i++) scanf("%d",&num[i]),max1=max(max1,num[i]);
int le=0,ri=max1,ans;
while(ri>=le){
int mid=(le+ri)>>1;
if(judge(mid)) le=mid+1,ans=mid;
else ri=mid-1;
}
printf("%d\n",ans);
}
return 0;
}