这种题只能二分答案把qwwq,直接做根本做不了啊。。。
首先你需要知道如何通过 一个区间<=x的数有多少个 来判断x和这个区间中位数的关系。
很显然当数有至少 [L/2]+1 个(L是区间内数的个数)时,x>=该区间的中位数。
你肯定觉得这多简单啊?有啥子用?
第一,它可以转化成,区间内<=x的数比剩下的数多的时候,x>=该区间的中位数,于是就可以做二分里面套的部分。
具体的来说,就是我们二分到一个x的时候,希望知道有多少个区间的中位数<=x。
这个时候只需要把<=x的数设置成1,其他的设置成-1,然后算一算有多少区间的数的和是正数,这显然就是一个离散化+树状数组的傻逼问题。
第二,它还可以用来作最外层的二分判断,调整二分的上下界。
这个比较好想,我就不说了2333。
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cmath> #define ll long long using namespace std; const int N=1e5+5; int n,m,f[N],ans,a[N],mid,b[N],c[N],ky; ll num; inline void update(int x,int y){ for(;x<=ky;x+=x&-x) f[x]+=y;} inline int query(int x){ int an=0; for(;x;x-=x&-x) an+=f[x]; return an;} inline ll calc(){ ll an=0; b[0]=0,memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) b[i]=b[i-1]+(a[i]<=mid?1:-1),c[i]=b[i]; c[ky=n+1]=0,sort(c+1,c+ky+1),ky=unique(c+1,c+ky+1)-c-1; for(int i=0;i<=n;i++) b[i]=lower_bound(c+1,c+ky+1,b[i])-c; update(b[0],1); for(int i=1;i<=n;i++) an+=(ll)query(b[i]-1),update(b[i],1); return an; } inline void solve(){ int L=1,R=1e9; while(L<=R){ mid=L+R>>1; if(calc()>=num) ans=mid,R=mid-1; else L=mid+1; } } int main(){ scanf("%d",&n),num=n*(ll)(n+1)>>1,num=(num>>1)+1; for(int i=1;i<=n;i++) scanf("%d",a+i); solve(); printf("%d ",ans); return 0; }