二分树状数组-洛谷P1168 中位数
来源:互联网 发布:redis mac 安装配置 编辑:程序博客网 时间:2024/06/12 03:38
https://www.luogu.org/problem/show?pid=1168
本来和fopzz想练练树状数组,就搜索到了这道题;
TM二分的条件搞了一个下午;
基本思想就是二分寻找答案,然后用树状数组去维护有几个比这个二分出来的值大,然后就没有了;
数据要离散,这个好像用map也可以,但是不推荐;
我一开始TLE然后就以为是map慢,结果改好后是降了600ms;
那怎么离散呢?
我们先把a数组读入并复制给b数组;
然后排序a;
这个时候a数组就有序了,我们就可以把b数组里的值通过二分找到其在a数组里的下标,这样就把1~1e9的数据压缩到1e5了;
这样的离散支持去重,支持不去重;
离散好了我们咋么搞呢?
树状数组怎么来维护比x小的数的个数呢?;
我们能用树状数组来维护前=前缀和;
那我们每增加一个数,我们就把他当作下标,在上面+1;
然后我统计小于等于x的个数时直接取x的前缀和好了;
对于二分求答案,从1~n里二分;
因为离散后数据一定再1~n里面;
对于一个数吧,有三种情况
- 没出现过这个数
- 这个数恰好有一个
- 这个数有很多
因为个数是奇数,所以我们枚举到一个空数时,比他小的个数必然不等于比他大的,可以继续二分;
然后恰好有一个,我们直接找到有几个比他小,如果是总数div2就是答案了;
如果有多个,设数是x,那显然 <=x的 减 小于x的 大于1;
这时如果<=x大于总数div2,小于x的小于总数div2,答案就是x;
#include<cstdio>//cfb#include<cstdlib>#include<iostream>#include<algorithm>#include<cmath>#include<map>using namespace std;int a[100001],b[100001],c[100001];bool vi[100001];int n,ans,nn,x;void add(int x,int y){ for(int i=x;i<=n;i+=i&-i)c[i]+=y;}int out(int x){ int ans=0;for(int i=x;i;i-=i&-i)ans+=c[i];return ans;}void outit(int num){ int l=1,r=n,ans; while(r>=l){ int mid=l+r>>1; int sum=out(mid-1); int s=out(mid);//为什么这里是>而不是>=,因为s包含答案自己,要-1 if(vi[mid]&&((sum<num&&s>num)||sum==num)){ans=mid;break;} if(sum>num)r=mid-1;else l=mid+1; } printf("\n%d",a[ans]);}int er(int x){ int l=1,r=n,ans; while(1){ int mid=l+r>>1; if(a[mid]==x)return mid; if(a[mid]>x)r=mid-1;else l=mid+1; }}int main(){ scanf("%d",&n); if(!(n&1))n--; for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];x=a[1]; sort(a+1,a+n+1); for(int i=1;i<=n;i++)b[i]=er(b[i]); printf("%d",x); add(b[1],1);vi[b[1]]=1; for(int i=3;i<=n;i+=2){ add(b[i-1],1); add(b[i],1); vi[b[i-1]]=vi[b[i]]=1; outit(i>>1); }}
0 0
- 二分树状数组-洛谷P1168 中位数
- |洛谷|堆|P1168 中位数
- 洛谷 P1168 中位数
- 洛谷 P1168 中位数
- 洛谷P1168 中位数
- 洛谷P1168 中位数
- 洛谷P1168 中位数(堆)
- P1168 中位数
- 洛谷P3031 [USACO11NOV](中位数,树状数组)
- 考试题 树状数组查找以比x大的数作为中位数的个数+二分中位数
- poj2892 树状数组+二分
- poj2182(二分+树状数组)
- hdu5493 树状数组+二分
- hdu5493Queue 树状数组+二分
- hdoj5493【树状数组+二分】
- HDU2852【树状数组+二分】
- Codeforces846D(二分+树状数组)
- CodeForces540E【树状数组+二分】
- 基于hadoop的社交网络三角形计数
- 华硕笔记本 Windows 10 如何从USB光驱中开机
- 使用DPDK l3fwd测试硬件吞吐性能
- IPC简介
- Internet Protocol Address and Network Mask
- 二分树状数组-洛谷P1168 中位数
- shell(1)shell概述
- 程序员的英语学习!!对于像进一步提升自己的人来说,很重要哟!
- HDU 1004 Let the Balloon Rise
- 字符串长度的计算:sizeof和strlen的使用
- GIMR默认使用HugePages
- 做一个罐子
- Ubuntu下把桌面路径改成自定义路径
- iOS开发笔记之六十二——如何构建大型App的Crash符号化系统