luogu P3871 [TJOI2010]中位數
阿新 • • 發佈:2018-12-09
luogu P3871 [TJOI2010]中位數
平衡樹模板?
貌似是的
寫個插入和左右旋以及查詢Kth就可以了
std:
#include<bits/stdc++.h>
using namespace std;
const int N=2000000;
struct node{//結構體重建樹
int l;//左兒子
int r;//右兒子
int k;//權值
int p;//優先順序
int c;//重複元素個數
int s;//子節點個數
#define l(x) t[x].l
#define r(x) t[x].r
#define v(x) t[x].k
#define p(x) t[x].p
#define c(x) t[x].c
#define s(x) t[x].s
}t[N];
int pool=0;
int root;
int n;
int data;
int v=0;
inline void upt(const int &k){//傳遞
s(k)=s(l(k))+s(r(k))+c(k);
}
inline void zig(int &k){//左旋
int y=l(k);
l(k)=r(y);
r(y)=k;
s(y)=s(k);
upt (k);
k=y;
}
inline void zag(int &k){//右旋
int y=r(k);
r(k)=l(y);
l(y)=k;
s(y)=s(k);
upt(k);
k=y;
}
inline void ins(int &k,const int &val){//插入節點
if(!k){//新建一個節點
k=++pool;
v(k)=val;
p(k)=rand();//賦值一個隨機的優先順序
c(k)=s(k)=1;
l (k)=r(k)=0;//沒有左右兒子
return;
}
else ++s(k);
if(v(k)==val) ++c(k);//有重複元素
else if(val<v(k)){
ins(l(k),val);
if(p(l(k))<p(k)) zig(k);//左旋:維護堆性質
}
else{
ins(r(k),val);
if(p(r(k))<p(k)) zag(k);//右旋:維護堆性質
}
}
int Rk(const int &val){
int x=root;
int res=0;
while(x){
if(val==v(x)) return res+s(l(x))+1;//找到了:返回排名
if(val<v(x)) x=l(x);
else res+=s(l(x))+c(x),x=r(x);
}
}
inline int serch_min(const int &val){
int x=root,res=-2147483647;
while(x){
if(v(x)<val) res=v(x),x=r(x);
else x=l(x);
}
return res;
}
inline int serch_max(const int &val){
int x=root,res=-2147483647;
while(x){
if(v(x)>val) res=v(x),x=l(x);
else x=r(x);
}
return res;
}
inline int Kth(int k){
int x=root;
while(x){
if(s(l(x))<k&&s(l(x))+c(x)>=k) return v(x);
if(s(l(x))>=k) x=l(x);
else k-=s(l(x))+c(x),x=r(x);
}
return 0;
}
inline void del(int &k,const int &val){
if(v(k)==val){
if(c(k)>1) --c(k),--s(k);
else if(!l(k)||!r(k)) k=l(k)+r(k);
else if(p(l(k))<p(r(k))) zig(k),del(k,val);
else zag(k),del(k,val);
return;
}
--s(k);
if(val<v(k)) del(l(k),val);
else del(r(k),val);
return;
}
int main(){
//freopen("a.out","w",stdout);
int cnt=0;
srand((unsigned)time(NULL));
cin >> n;
for(int i=1;i<=n;i++){
scanf("%d",&data);
ins(root,data);
}
v=n;
int m;
cin >> m;
while(m--){
char c;
cin >> c;
if(c=='a'){
cin >> c >> c;
scanf("%d",&data);
ins(root,data);
v++;
}
else{
cin >> c >> c;
int u=(v+1)/2;
printf("%d\n",Kth(u));
}
}
return 0;
}