Description
定义一个长度为奇数的区间的值为其所包含的的元素的中位数.
现给出$n$个数,求将所有长度为奇数的区间的值排序后,第$k$大的值为多少.
Input
第一行两个数$n$和$k$.第二行$n$个数$a_i$.
Output
一个数表示答案.
Sample Input
4 3
3 1 2 4
Sample Output
2
HINT
$1;leq;n;leq;10^5,k;leq;$奇数区间的数量,$0;leq;a_i<2^{31}$
Solution
二分答案$ans$,统计长度为奇数的区间的值$;geq;ans$的区间数.
把所有$a_i;geq;ans$的位置标为$1$,所有$a_i<ans$的位置标为$0$,求出前缀和$sum[;]$.
则值$;geq;ans$的区间$[j,i]$满足条件$sum_i-sum_{j-1}>frac{i-j+1}{2}$($i,j$同号).
移项得,$2; imes;sum_i-i>2; imes;sum_{j-1}-(j-1)$.
即用树状数组维护顺序对即可.
#include<cmath> #include<ctime> #include<queue> #include<stack> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 100005 using namespace std; typedef long long ll; ll a[N],b[N],k; int s[2][N*3],sum[N],n,m,l,r,mid; inline int lowbit(int x){ return x&(-x); } inline int ask(int k,int j){ int ret=0; for(int i=k;i;i-=lowbit(i)) ret+=s[j][i]; return ret; } inline void add(int k,int j){ for(int i=k;i<=m;i+=lowbit(i)) ++s[j][i]; } inline bool chk(ll x){ ll cnt=0LL; memset(s,0,sizeof(s)); for(int i=1;i<=n;++i) if(a[i]>=x) sum[i]=sum[i-1]+1; else sum[i]=sum[i-1]; for(int i=1,tmp;i<=n;++i){ tmp=(sum[i]<<1)-i+n; cnt+=(ll)(ask(tmp,i&1^1)); add(tmp,i&1); if((i&1)&&(sum[i]<<1)-i>=0LL) ++cnt; } return cnt>=k; } inline void init(){ scanf("%d%lld",&n,&k); for(int i=1;i<=n;++i){ scanf("%lld",&a[i]); b[i]=a[i]; } l=1;r=n;m=n*3; sort(b+1,b+1+n); while(l<r){ mid=(l+r+1)>>1; if(chk(b[mid])) l=mid; else r=mid-1; } printf("%lld ",b[l]); } int main(){ freopen("kth.in","r",stdin); freopen("kth.out","w",stdout); init(); fclose(stdin); fclose(stdout); return 0; }