zoukankan      html  css  js  c++  java
  • 中位数之中位数「NOIP多校联考 2019」

    题意

    给出一个长度为n的序列a,首先求出其所有区间的中位数,将这些中位数构成的集合记为S,求S中所有数的中位数。

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


    思路

    这道题还是比较巧妙的。(orz (mhy),(zhh)

    我们可以二分答案,这个显然是有单调性的。那么只要求出值不超过枚举的mid的中位数的数量即可。

    我们定义数组(p[i])表示前i个数中超过mid的数的数量。

    那么每一个符合条件的区间就会满足:(r-l>2*(p[r]-p[l]))(超过mid的数的数量没有达到区间总数的一半)

    移一下项得到(r-2*p[r]>l-2*p[l])

    于是我们就将其转换为一个逆序对问题了,每一次check的时候将i-p[i]插入树状数组中然后统计即可。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
    	template<typename T>inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    
    	template<typename T>inline void write (T x) {
    		if (x<0) putchar('-'),x*=-1;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    namespace Project {
    	#define int long long
    	
    	const int N=100100;
    	
    	int n;
    	int a[N],p[N],llim=0x3f3f3f3f3f3f,rlim;
    	int tree[N<<2];
    	
    	inline int lowbit (int x) {
    		return x&(-x);
    	}
    	inline void update (int x,int v) {
    		for (register int i=x; i<n*4; i+=lowbit(i)) tree[i]+=v;
    	}
    	inline int query (int x) {
    		int res=0;
    		for (register int i=x; i; i-=lowbit(i)) res+=tree[i];
    		return res;
    	}
    	inline bool check (int x) {
    		int res=0;memset(tree,0,sizeof(tree));
    		for (register int i=1; i<=n; ++i) 
    			p[i]=p[i-1]+2*(a[i]>x);
    //		update(n,1);
    		for (register int i=1; i<=n; ++i) {
    			update(i-p[i]+2*n,1);
    			res+=query(i-p[i]-1+2*n);
    		}
    		return (res>=n*(n+1)/4);
    	}
    	
    	inline void MAIN () {
    		read(n);
    		for (register int i=1; i<=n; ++i) {
    			read(a[i]),llim=min(llim,a[i]),rlim=max(rlim,a[i]);
    		}
    		int mid,ans;
    		while (llim<=rlim) {
    			mid=(llim+rlim)>>1;
    			if (check(mid)) rlim=mid-1,ans=mid;
    			else llim=mid+1;
    		}
    		write(ans);
    	}
    	
    	#undef int
    }
    
    int main () {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	Project::MAIN();
    }
    
    
  • 相关阅读:
    Redis 设计与实现-内部数据结构
    RuntimeBinderException 异常
    IPv4和IPv6地址库
    -Xms -Xmx -Xmn -Xss -XX:
    倒计时
    列表操作-分片赋值
    20175316毕设准备Day1-2
    20175316毕业设计——基于区块链服务的仓库管理系统
    Python学习笔记:sys.argv入参
    Python学习笔记:bisect模块实现二分搜索
  • 原文地址:https://www.cnblogs.com/ilverene/p/11784697.html
Copyright © 2011-2022 走看看