luoguP3871 [TJOI2010]中位数

Date: Tue 30 October 2018
Updated: Tue 30 October 2018

In 5. OI.

Tags: OI

题目


显然中位数为排序后第(n+1)/2个数

define m (n+1)/2

考虑维护两个堆

一个大根堆(s1),里面为前m个元素;一个小根堆(s2),里面为后n-m个元素

修改和询问的流程如下

每次加入一个数x时

如果x<=s1.top

​ add x to s1

​ 如果|s1|>|s2|+1

​ move s1.top to s2

else

​ add x to s2

​ 如果|s2|>|s1|

​ move s2.top to s1

每次询问

输出s1.top

显然正确

#include<bits/stdc++.h>
#define fsb(a,b,c) for(int a=b;a<=c;a++)
#define fbs(a,b,c) for(int a=b;a>=c;a--)
using namespace std;
int n=0,m,x,sz1=0,sz2=0;
char s[10];
struct node1{
 int x;
};
struct node2{
 int x;
};
int operator<(node1 a,node1 b){
 return a.x<b.x;
}
int operator<(node2 a,node2 b){
 return a.x>b.x;
}
priority_queue<node1>s1;
priority_queue<node2>s2;
template<typename qw>inline void rll(qw &x){
 qw f=1;x=0;char c=getchar();
 while(!isdigit(c))f=c=='-'?-1:f,c=getchar();
 while(isdigit(c))x=x*10+c-'0',c=getchar();
 x*=f;
}
inline void add(int x){
 if(s1.empty()){
  s1.push((node1){x});sz1++;return;
 }
 if(x<=s1.top().x){
  s1.push((node1){x});sz1++;
  if(sz1>sz2+1){
   int t=s1.top().x;s1.pop();
   s2.push((node2){t});sz1--;sz2++;
  }
 }else{
  s2.push((node2){x});sz2++;
  if(sz2>sz1){
   int t=s2.top().x;s2.pop();
   s1.push((node1){t});sz1++;sz2--;
  } 
 }
}
int main(){
 rll(m);
 fsb(i,1,m){
  rll(x);add(x);
 }
 rll(m);
 fsb(i,1,m){
  scanf("%s",s+1);
  if(s[1]=='a'){
   rll(x);add(x);
  }else{
   printf("%d\n",s1.top().x);
  }
 }
 return 0;
}

Social