權值線段樹,是以權值爲下標的線段樹,不像普通的線段樹一樣。
但是對於較大的數據,就需要離散化來解決空間上的不足。
權值線段樹這樣一說,有點兒像主席樹的感覺。空間上也優於主席樹。但是它對於子區間卻無能爲力。它對於一些動態的整個區間上的查詢還是比較好用。
就像hdu5249就是動態中位數,就可以這樣來處理。
附上代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define Set(aa,bb) memset(aa,bb,sizeof(aa))
#define ls node<<1
#define rs node<<1|1
using namespace std;
const int maxn=10010;
int pre[maxn],now[maxn],tree[maxn<<2];
int n,Case;
void pushup(int node){
tree[node]=tree[ls]+tree[rs];
}
void create_tree(int node,int l,int r){
if(l==r){
tree[node]=0;
return ;
}
int mid=(l+r)>>1;
create_tree(ls,l,mid);
create_tree(rs,mid+1,r);
pushup(node);
return ;
}
void update(int node,int l,int r,int w,int flag){
if(l==r){
tree[node]+=flag;
return ;
}
int mid=(l+r)>>1;
if(w<=mid) update(ls,l,mid,w,flag);
else update(rs,mid+1,r,w,flag);
pushup(node);
}
int query(int node,int l,int r,int flag){
if(l==r) return l;
int mid=(l+r)>>1;
if(flag<=tree[ls]) return query(ls,l,mid,flag);
else return query(rs,mid+1,r,flag-tree[ls]);
}
void work(){
queue<int>q;
++Case;
printf("Case #%d:\n",Case);
For(i,1,n){
char s[10];
scanf("%s",s);
if(s[0]=='i') scanf("%d",&pre[i]);
else if(s[0]=='o') pre[i]=-1;
else pre[i]=-2;
}
int sum=0;
For(i,1,n){
if(pre[i]>=0) now[++sum]=pre[i];
}
sort(now+1,now+1+sum);
sum=unique(now+1,now+sum+1)-(now+1);
create_tree(1,1,sum);
For(i,1,n){
if(pre[i]>=0){
int tmp=lower_bound(now+1,now+1+sum,pre[i])-now;
update(1,1,sum,tmp,1);
q.push(pre[i]);
}
else if(pre[i]==-1){
int ret=q.front();
int tmp=lower_bound(now+1,now+1+sum,ret)-now;
update(1,1,sum,tmp,-1);
q.pop();
}
else{
int md=query(1,1,sum,(q.size()/2)+1);
printf("%d\n",now[md]);
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
while(~scanf("%d",&n)) work();
return 0;
}