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;
}