#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
#define maxn 100000
#define LL long long
int key[maxn],sz[maxn];
int ch[maxn][2],cnt,root,top;
void Rotate(int &x,int f){
int y=ch[x][!f];
ch[x][!f]=ch[y][f];
ch[y][f]=x;
sz[y]=sz[x];
sz[x]=sz[ch[x][0]] + sz[ch[x][1]] + 1;
x = y;
}
void Maintain(int &x, int f){
if(sz[ch[ch[x][f]][f]] > sz[ch[x][!f]]) Rotate(x,!f);
else if(sz[ch[ch[x][f]][!f]] > sz[ch[x][!f]]){
Rotate(ch[x][f],f);Rotate(x,!f);
}
else return;
Maintain(ch[x][0],0);
Maintain(ch[x][1],1);
Maintain(x,1);
Maintain(x,0);
}
void Insert(int &x, int k){
if(x==0){
x = ++top;sz[x]=1;
ch[x][0] = ch[x][1] = 0;
key[x] = k;
}
else{
sz[x]++;
Insert(k<key[x]?ch[x][0]:ch[x][1],k);
Maintain(x,k>=key[x]);
}
}
int Remove(int &x, int k){
int d_key;
if(!x) return -1;
sz[x]--;
if(k==key[x] || (!ch[x][0] && k<key[x]) || (!ch[x][1] && k>key[x])){
d_key = key[x];
if(ch[x][0] && ch[x][1]) key[x]=Remove(ch[x][0],k+1);
else x = ch[x][0] + ch[x][1];
}
else d_key = Remove(k>key[x]?ch[x][1]:ch[x][0],k);
return d_key;
}
int Select(int x, int k){
int r = sz[ch[x][0]] + 1;
if(k==r) return key[x];
else if(k>r) return Select(ch[x][1],k-r);
else return Select(ch[x][0],k);
}
void print(){
if(cnt&1) printf("%d\n",Select(root,cnt/2+1));
else{
LL ans1 = (LL)Select(root,cnt/2);
LL ans2 = (LL)Select(root,cnt/2+1);
LL ans = ans1 + ans2;
if(ans%2==0) printf("%lld\n",ans/2);
else printf("%.1f\n",ans/2.0);
}
}
int find(int root,int k){
if(!root) return 0;
if(key[root]==k) return 1;
if(k>key[root]) return find(ch[root][1],k);
else return find(ch[root][0],k);
}
int main(){
int cs,q,a;char str[20];
scanf("%d",&cs);
while(cs--){
scanf("%d",&q);
root=0;top=0;cnt=0;
while(q--){
scanf("%s%d",str,&a);
if(str[0]=='r'){
if(!find(root,a)) puts("Wrong!");
else{
Remove(root,a);
cnt=max(0,cnt-1);
if(!cnt) puts("Empty!");
else print();
}
}
else{
Insert(root,a);
cnt++;print();
}
}
}
return 0;
}
题意:给定集合,每次插入和删除元素,求中位数。
方法: 利用SBT动态求区间第K大