题目描述:
有三种操作
in x 表示加入数 x
out 表示 弹出最早元素
query 表示查询当前的序列中位数 即 第 floor(m/2)+1 的数字
题目分析:
裸的权值线段树:
我还以为啥叫权值线段树,其实就是以值当做下标的线段树
主要是求动态 Kth 的
其实主席树就是可持久化的权值线段树!!!
值域较大,需要整一整离散化啊!
题目链接:
Ac 代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define xclear(x,y) memset(x,y,sizeof(x))
const int maxm=1e6+100;
int num[maxm],val[maxm];
int tree[maxm<<2];
int stk[maxm],top;
int n,Case;
void update(int o)
{
tree[o]=(tree[(o<<1)]+tree[(o<<1)|1]);
}
void build(int o,int l,int r)
{
if(l>=r)
{
tree[o]=0;
return;
}
int mid=(l+r)>>1;
build((o<<1),l,mid);
build((o<<1)|1,mid+1,r);
update(o);
}
void change(int o,int l,int r,int ind,int flag)
{
if(l>=r)
{
tree[o]+=flag;
return;
}
int mid=(l+r)>>1;
if(ind<=mid) change((o<<1),l,mid,ind,flag);
else change((o<<1)|1,mid+1,r,ind,flag);
update(o);
}
int ask(int o,int l,int r,int ind)
{
if(l>=r) return l;
int mid=(l+r)>>1;
if(ind<=tree[(o<<1)]) return ask((o<<1),l,mid,ind);
else return ask((o<<1)|1,mid+1,r,ind-tree[(o<<1)]);
}
void work()
{
++Case;
printf("Case #%d:\n",Case);
xclear(tree,0),xclear(num,0);
int cnt=0;
std::queue <int> dl;
for(int i=1;i<=n;i++)
{
char s[10];
scanf("%s",s);
if(s[0]=='i') scanf("%d",&num[i]),val[++cnt]=num[i];
if(s[0]=='q') num[i]=-1;
if(s[0]=='o') num[i]=-2;
}
std::sort(val+1,val+cnt+1);
int tot=std::unique(val+1,val+cnt+1)-val-1;
//build(1,1,tot);
for(int i=1;i<=n;i++)
{
if(num[i]>=0)
{
int id=std::lower_bound(val+1,val+tot+1,num[i])-val;
dl.push(id);
change(1,1,tot,id,1);
}
if(num[i]==-1)
{
int fx=dl.size()/2+1;
printf("%d\n",val[ask(1,1,tot,fx)]);
}
if(num[i]==-2)
{
int id=dl.front();
dl.pop();
change(1,1,tot,id,-1);
}
}
}
int main()
{
while((scanf("%d",&n))!=EOF) work();
return 0;
}