http://poj.org/problem?id=1442
题意:对一个序列进行两个操作:
- ADD(x):表示将x加入序列
- GET:表示获取序列中的第k大的数,k为GET出现的次数
现给出两个序列Ai和Ui,表示进行n次ADD(Ai)操作,并进行m次GET操作,其中GET操作获取的是前Ui个数中的第i大的数。
所以这是道平衡树的模板题,网上还有用两个优先队列,一个大根堆,一个小根堆做的,就是大根堆放i个,小根堆放Ui-i个。
Treap的板子是借鉴的这位神犇的博客https://blog.csdn.net/acdreamers/article/details/11309971
Treap版
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct Treap
{
int size;
int key,fix;
Treap* ch[2];
Treap(int key)
{
size=1;
fix=rand();
this->key=key;
ch[0]=ch[1]=NULL;
}
int cmp(int x) const
{
if(x==key) return -1;
return x<key?0:1;
}
void Maintain()
{
size=1;
if(ch[0]!=NULL) size+=ch[0]->size;
if(ch[1]!=NULL) size+=ch[1]->size;
}
};
int val[1000010];
void Rotate(Treap* &t,int d)
{
Treap* k=t->ch[d^1];
t->ch[d^1]=k->ch[d];
k->ch[d]=t;
t->Maintain();
k->Maintain();
t=k;
}
void Insert(Treap* &t,int x)
{
if(t==NULL) t=new Treap(x);
else
{
int d=x < t->key?0:1;
Insert(t->ch[d],x);
if(t->ch[d]->fix > t->fix)
Rotate(t,d^1);
}
t->Maintain();
}
void Delete(Treap* &t,int x)
{
int d=t->cmp(x);
if(d==-1)
{
Treap* tmp=t;
if(t->ch[0]==NULL)
{
t=t->ch[1];
delete tmp;
tmp=NULL;
}
else if(t->ch[1]==NULL)
{
t=t->ch[0];
delete tmp;
tmp=NULL;
}
else
{
int k=t->ch[0]->fix > t->ch[1]->fix ? 1:0;
Rotate(t,k);
Delete(t->ch[k],x);
}
}
else Delete(t->ch[d],x);
if(t!=NULL) t->Maintain();
}
bool Find(Treap* t,int x)
{
while(t!=NULL)
{
int d=t->cmp(x);
if(d==-1) return true;
t=t->ch[d];
}
return false;
}
int Kth(Treap* t,int k)
{
if(t==NULL||k<=0||k>t->size)
return -1;
if(t->ch[0]==NULL&&k==1)
return t->key;
if(t->ch[0]==NULL)
return Kth(t->ch[1],k-1);
if(t->ch[0]->size>=k)
return Kth(t->ch[0],k);
if(t->ch[0]->size+1==k)
return t->key;
return Kth(t->ch[1],k-1-t->ch[0]->size);
}
int Rank(Treap* t,int x)
{
int r;
if(t->ch[0]==NULL) r=0;
else r=t->ch[0]->size;
if(x==t->key) return r+1;
if(x<t->key)
return Rank(t->ch[0],x);
return r+1+Rank(t->ch[1],x);
}
void DeleteTreap(Treap* &t)
{
if(t==NULL) return ;
if(t->ch[0]!=NULL) DeleteTreap(t->ch[0]);
if(t->ch[1]!=NULL) DeleteTreap(t->ch[1]);
delete t;
t=NULL;
}
void Print(Treap* t)
{
if(t==NULL) return ;
Print(t->ch[0]);
cout<<t->key<<endl;
Print(t->ch[1]);
}
int main()
{
int n,m,x;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
int id=1;
Treap* root=NULL;
for(int i=1;i<=m;i++)
{
scanf("%d",&x);
for(int j=id;j<=x;j++)
Insert(root,val[j]);
id=x+1;
printf("%d\n",Kth(root,i));
}
DeleteTreap(root);
return 0;
}
优先队列版
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
using namespace std;
int val[1000010];
int main()
{
priority_queue<int, vector<int>, greater<int> >q1;//小根堆
priority_queue<int> q2;//大根堆
int n,m,a[30005],t;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d", &val[i]);
int i=1;
while(m--)
{
scanf("%d",&t);
while(i<=t)
{
q1.push(val[i]);
i++;
if(!q2.empty()&&q2.top()>q1.top())
{
int temp=q2.top();
q2.pop();
q2.push(q1.top());
q1.pop();
q1.push(temp);
}
}
printf("%d\n",q1.top());
q2.push(q1.top());
q1.pop();
}
return 0;
}