• 【洛谷U142585】中位数之中位数


    题目

    题目链接:https://www.luogu.com.cn/problem/U142585
    给出一个长度为 (n) 的序列 (a),首先求出其所有区间的中位数,将这些中位数构成的集合记为 (S),求 (S) 中所有数的中位数。

    这里定义的中位数指:对于 (m) 个数,将其从小到大排序后,第 ((frac{m}{2}+1)) 个数即为中位数,例如 ((10,30,20)) 的中位数为 (20)((10,30,20,40)) 的中位数为 (30)((10,10,10,20,30)) 的中位数为 (10)

    思路

    套路性二分将序列转化为 (1,-1) 序列。
    然后做一遍前缀和,问题转化为 (sum^{n}_{i=1}sum^{i-1}_{j=0}[s_i-s_jgeq 0]) 是否非负。
    用树状数组计算一下即可。
    时间复杂度 (O(nlog nlog A))。其中 (A=max(a_i))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=200010;
    int n,a[N],s[N];
    ll sum;
    
    struct BIT
    {
    	int c[N];
    	
    	void add(int x,int v)
    	{
    		for (int i=x;i<N;i+=i&-i)
    			c[i]+=v;
    	}
    	
    	int query(int x)
    	{
    		int sum=0;
    		for (int i=x;i;i-=i&-i)
    			sum+=c[i];
    		return sum;
    	}
    }bit;
    
    int main()
    {
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	int l=1,r=1e9,mid;
    	while (l<=r)
    	{
    		mid=(l+r)>>1; sum=0; s[0]=1e5+1;
    		memset(bit.c,0,sizeof(bit.c));
    		bit.add(s[0],1);
    		for (int i=1;i<=n;i++)
    		{
    			if (a[i]>=mid) s[i]=s[i-1]+1;
    				else s[i]=s[i-1]-1;
    			sum+=2*bit.query(s[i])-i;
    			bit.add(s[i],1);
    		}
    		if (sum>=0) l=mid+1;
    			else r=mid-1;
    	}
    	printf("%d
    ",l-1);
    	return 0;
    }
    
  • 相关阅读:
    linux学习之uniq
    hive学习05 参数设置
    【python】调用sm.ms图床api接口,实现上传图片并返回url
    【python】列表与数组之间的相互转换
    更新yum源
    要把RAID5创建卷组
    named-checkconf -z /etc/named.conf
    function_exists
    trigger_error
    命名空间
  • 原文地址:https://www.cnblogs.com/stoorz/p/14048929.html
Copyright © 2020-2023  润新知