方法一1:用两个优先队列,一个从小到大(k+1)A,堆顶元素就是中位数;一个从大到小B。每次来两个新数,小就放B,大就放A。前面的多了向后放,后面多了向前倒。
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int n,a1;
priority_queue<int,vector<int> ,greater<int> >minheap;
priority_queue<int>maxheap;
int main() {
scanf("%d%d",&n,&a1);
printf("%d\n",a1);
minheap.push(a1);
for(int i=3; i<=n; i+=2) {
int a,b;
scanf("%d%d",&a,&b);
if(a>minheap.top())minheap.push(a);
else maxheap.push(a);
if(b>minheap.top())minheap.push(b);
else maxheap.push(b);
while(maxheap.size()>=minheap.size()) {
minheap.push(maxheap.top());
maxheap.pop();
}
while(maxheap.size()<minheap.size()-1) {
maxheap.push(minheap.top());
minheap.pop();
}
printf("%d\n",minheap.top());
}
return 0;
}
方法二:求k大值,用权值线段数
//权值线段树,离散化数据后,在对应的位置插入1,
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 230000
int a[N],b[N];
int n,m;
struct node {
int l,r,sum;//sum,所有离散化后数字的权值和
int val;
} t[N*4];
inline void build(int p,int l,int r) {
t[p].l=l,t[p].r=r;
if(l==r)return;
int m=(l+r)>>1;
build(p<<1,l,m);
build(p<<1|1,m+1,r);
}
void query(int p,int pos) {//查询从1到哪个点截至,权值和正好为pos
if(t[p].l==t[p].r) {
printf("%d\n",t[p].val);
return;
}
int x=t[p<<1].sum;//
if(x>=pos)query(p<<1,pos);
else query(p<<1|1,pos-x);
}
void Insert(int p,int pos,int val) {
if(t[p].l==t[p].r&&t[p].l==pos) {
t[p].val=val;
t[p].sum++;
return;
}
int m=(t[p].l+t[p].r)>>1;
if(pos>m)Insert(p<<1|1,pos,val);
else
Insert(p<<1,pos,val);
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
}
int main() {
cin>>n;
m=(n+1)>>1;
build(1,1,n);
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
int k=lower_bound(b+1,b+n+1,a[1])-b;
Insert(1,k,a[1]);
query(1,1);
for(int i=1; i<m; i++) {
k=lower_bound(b+1,b+n+1,a[i<<1])-b;
Insert(1,k,a[i<<1]);
k=lower_bound(b+1,b+n+1,a[i<<1|1])-b;
Insert(1,k,a[i<<1|1]);
query(1,i+1);
}
return 0;
}
方法三:权值线段树可以,树状数组当然行啦
但树状数组没法查询和的截至位置,用二分答案
//树状数组、二分答案,
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 230000
int a[N],b[N],c[N];
int n,m;
int lowbit(int x){return x&-x; }
void add(int i,int val){
for(;i<=n;i+=lowbit(i))
c[i]+=val;
}
int query(int i){// 求前i项的和
int ans=0;
for(;i;i-=lowbit(i))ans+=c[i];
return ans;
}
int half(int val) {
int l=1,r=n,mid,ans;
while(l<=r){
mid=(l+r)/2;
if(query(mid)<val)l=mid+1;
else ans=mid,r=mid-1;
}
return b[ans];
}
int main() {
cin>>n;
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
int k=lower_bound(b+1,b+n+1,a[1])-b;
add(k,1);
printf("%d\n",a[1]);
for(int i=1; i<=(n-1)/2; i++) {
k=lower_bound(b+1,b+n+1,a[i<<1])-b;
add(k,1);
k=lower_bound(b+1,b+n+1,a[i<<1|1])-b;
add(k,1);
printf("%d\n",half(i+1));
}
return 0;
}
方法四,中位数,平衡树正好可以求,写不出来:(