2022-08-26 QLUACM暑假训练5 I题题解

D - Median of Medians (atcoder.jp)

中位数和平均数都有01串的性质,所以我们可以先二分答案mid,找到有哪些数大于等于mid设为1,哪些数小于mid设为-1,然后找哪些区间有至少n/2个正数即转变成了和大于等于0的区间有多少个,那么自然想到要用前缀和处理一下,这样可以o1内查询一段区间的和。然后就转变成了一个经典的二位偏序的题目——即x<y且sum[x]<=sum[y]的区间有多少个,即可利用树状数组或者归并排序的做法解决。

#include<bits/stdc++.h>
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define fi first
#define se second
#define endl '\n'
#define bug printf("bug\n");
using namespace std;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
const long long LNF=0x3f3f3f3f3f3f3f3f;
const long long mod=1e9+7;
long long n;
long long s[N],st[N],sum[N];
long long res=0,num=0;

void mergesort(long long l,long long r){
    if(l==r) return ;
    long long mid=(l+r)>>1;
    mergesort(l,mid);  mergesort(mid+1,r);
    long long v1=l,v2=mid+1,cnt=l;
    while(v1<=mid&&v2<=r){
        if(sum[v1]<sum[v2]) st[cnt++]=sum[v1++];
        else res=res+(v1-l),st[cnt++]=sum[v2++];
    }
    while(v1<=mid) st[cnt++]=sum[v1++];
    while(v2<=r) res=res+(v1-l),st[cnt++]=sum[v2++];
    for(long long i=l;i<=r;i++) sum[i]=st[i];
}

bool check(int mid){
	res=0;
	for(int i=1;i<=n;i++){
		if(s[i]<=mid) sum[i]=1;
		else sum[i]=-1;
	}
	for(int i=1;i<=n;i++) sum[i]=sum[i-1]+sum[i];
	//for(int i=1;i<=n;i++) printf("%d ",sum[i]); puts("");
	mergesort(0,n);
	//printf("%d %d\n",mid,res);
	return res>=num/2+1;
}

void solve(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++) scanf("%lld",&s[i]);
	long long l=INF,r=0;
	for(long long i=1;i<=n;i++){
		l=min(l,s[i]); r=max(r,s[i]);
	}
	num=(n+1)*n/2;
	//printf("%lld\n",num);
	//printf("%d %d\n",l,r);
	while(l<r){
		long long mid=(l+r)>>1;
		if(check(mid)) r=mid;
		else l=mid+1;
	}
	printf("%lld\n",l);
}

int main(){
	int t=1;
	//scanf("%d",&t);
	while(t--){
		solve();
	}
	return 0 - 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值