权值线段树,是以权值为下标的线段树,不像普通的线段树一样。
但是对于较大的数据,就需要离散化来解决空间上的不足。
权值线段树这样一说,有点儿像主席树的感觉。空间上也优于主席树。但是它对于子区间却无能为力。它对于一些动态的整个区间上的查询还是比较好用。
就像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;
}