传送门
思路:
1.对顶堆,大根堆(从大到小)存较小的数,小根堆(从小到大)存较大的数。
如果当前数大于大根堆顶,就放入小根堆,否则放入大根堆。
然后维护使两堆容量大小之差小于等于1,然后容量较大的那个堆顶元素即是答案。
因为题目保证是求奇数个数的中位数,显然比中位数小的个数=比中位数大的个数,所以取多了那一个的堆顶即可。
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)。
#include
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair
#define fi first
#define se second
priority_queue<int>q1; //大根堆
priority_queue<int,vector<int>,greater<int> >q2;//小根堆
int main(){
int n,x;
scanf("%d%d",&n,&x);q1.push(x);
printf("%d\n",x);
for(int i=2;i<=n;i++){
scanf("%d",&x);
if(x>q1.top()) q2.push(x);
else q1.push(x);
while(abs((int)q1.size()-(int)q2.size())>1){
if(q1.size()>q2.size()) q2.push(q1.top()),q1.pop();
else q1.push(q2.top()),q2.pop();
}
if(i&1){
if(q1.size()>q2.size()) printf("%d\n",q1.top());
else printf("%d\n",q2.top());
}
}
return 0;
}
2.权值树状数组离散化+二分。
找中位数即是找第 k + 1 2 \dfrac{k+1}{2} 2k+1小的数。
显然我们可以二分枚举权值的大小是多少,即最大值最小化,大于等于 k + 1 2 \dfrac{k+1}{2} 2k+1的权值最小化即使权值答案,然后输出权值对于的元素即可。
#include
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair
#define fi first
#define se second
#define lowbit(x) x&(-x)
int n,tr[N],cnt,a[N],b[N];
void add(int x,int v){
while(x<=cnt) tr[x]+=v,x+=lowbit(x);
}
int sum(int x){
int ans=0;
while(x){
ans+=tr[x];
x-=lowbit(x);
}
return ans;
}
int Find(int x){
int l=1,r=cnt;
while(l<=r){
int mid=(l+r)>>1;
if(sum(mid)>=x) r=mid-1;
else l=mid+1;
}
return b[l];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
cnt=unique(b+1,b+n+1)-(b+1);
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
for(int i=1;i<=n;i++){
add(a[i],1);
if(i&1) printf("%d\n",Find((i+1)/2));
}
return 0;
}
3.对于第二种方式还可以用倍增法找权值,倒序枚举权值的位,找到小于 a n s ans ans的最大 i d id id,答案就是 b [ i d + 1 ] b[id+1] b[id+1]。
#include
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair
#define fi first
#define se second
#define lowbit(x) x&(-x)
int n,tr[N],cnt,a[N],b[N];
void add(int x,int v){
while(x<=cnt) tr[x]+=v,x+=lowbit(x);
}
int fun(int k){
int id=0,sum=0;
for(int i=20;i>=0;i--){
id+=(1<<i);
if(id>cnt||sum+tr[id]>=k) id-=(1<<i);
else sum+=tr[id];
}
return b[id+1];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
cnt=unique(b+1,b+n+1)-(b+1);
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
for(int i=1;i<=n;i++){
add(a[i],1);
if(i&1) printf("%d\n",fun((i+1)/2));
}
return 0;
}