ARC 101 D - Median of Medians

题面在这里!

 

    这种题只能二分答案把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\n",ans);
	return 0;
}

  

posted @ 2018-08-26 11:30  蒟蒻JHY  阅读(364)  评论(0编辑  收藏  举报