0
点赞
收藏
分享

微信扫一扫

动态中位数题目复盘

飞进科技 2022-02-06 阅读 77

1.从前到后遍历着求中位数

动态中位数—对顶堆

在这里插入图片描述

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 10010;
int n;
signed main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int cnt=0;
        priority_queue<int,vector<int>,greater<int>>up;
        priority_queue<int,vector<int>,less<int>>down;
        int a,n;
        cin>>a>>n;
        cout<<a<<" "<<(n+1)/2<<endl;
        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            if(down.empty()||down.top()>=x)down.push(x);
            else up.push(x);
            
            if(down.size()>up.size()+1)
            {
                up.push(down.top());
                down.pop();
            }
            if(up.size()>down.size())
            {
                down.push(up.top());
                up.pop();
            }
            if(i%2)
            {
                printf("%d ",down.top());
                if(++cnt%10==0)cout<<endl;
            }
        }
        if(cnt%10)cout<<endl;
    }
}

2.求大于等于k区间的最大中位数

Max Median—二分+贪心

在这里插入图片描述

题目链接

这题确实不好一下想到二分,但我们发现暴力的话一定会超时,其次中位数有一个很明显的性质,区间中大于等于中位数的个数大于小于中位数的个数
然后我们就发现了单调性。统计区间中大于等于中位数的个数和小于中位数的个数比较,大的话证明所选的数小了,小的话证明选的数大了

这题还让找出最大中位数,所以我们找到所有大于k的区间中,满足条件的最大值

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
const int N = 200010,mod=1e9+7;
int n,k;
int a[N],sum[N];
bool check(int x)
{
	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+(a[i]>=x?1:-1);
	int minv=0,maxv=0;
	//贪心,只要任意一个长度大于k的区间大于0就满足条件
	for(int i=k;i<=n;i++)
	{
		minv=min(minv,sum[i-k]);
		maxv=max(maxv,sum[i]-minv);
	}
	return maxv>0;
}
signed main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)scanf("%lld",a+i);
	int l=1,r=n;
	while(l<r)
	{
		int mid=l+r+1>>1;
		if(check(mid))l=mid;
		else r=mid-1;
	}
	cout<<l<<endl;
}

3.最多改变k次,求最大中位数

最大中位数

在这里插入图片描述

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
const int N = 200010;
int n,k;
int a[N];
bool check(int x)
{
    int res=0;
    for(int i=n/2+1;i<=n;i++)
    {
        if(a[i]<x)res+=x-a[i];
    }
    return res<=k;
}
signed main()
{
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++)scanf("%lld",a+i);
    sort(a+1,a+n+1);
    int l=1,r=2e9;
    while(l<r)
    {
        int mid=l+r+1>>1;
        if(check(mid))l=mid;
        else r=mid-1;
    }
    cout<<l<<endl;
    
}

4.和中位数相关的数学题

糖果传递在这里插入图片描述

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
const int N = 1000010;
int a[N];
int c[N];
signed main()
{
    int n;
    cin>>n;
    int ave=0;
    for(int i=0;i<n;i++)
    {
        scanf("%lld", &a[i]);
        ave+=a[i];
    }
    ave=ave/n;
    for(int i=n-1;i>0;i--){
         c[i]=c[i+1]+ave-a[i];
    }
    c[0]=0;
    sort(c,c+n);
    int res=0;
    for(int i=0;i<n;i++)res+=abs(c[i]-c[n/2]);
    cout<<res<<endl;
}
举报

相关推荐

0 条评论