这道题其实就是个splay裸题,而且只用写insert,findx,clear,update,rotate,splay这几个函数,加起来不到100行代码。
思路很简单,for(lef->u[i])insert(a[++lef])。然后查找排名为i的就好了。
CODE
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=300000+10;
int n,m,add=0,a[N],u[N],fa[N],ch[N][2],size[N],sz=0,cnt[N],key[N],root;
void clear(int x)
{
cnt[x]=fa[x]=key[N]=size[N]=ch[x][1]=ch[x][0]=0;
}
bool get(int x)
{
return ch[fa[x]][1]==x;
}
void update(int x)
{
if(!x)return;
size[x]=cnt[x];
if(ch[x][1])size[x]+=size[ch[x][1]];
if(ch[x][0])size[x]+=size[ch[x][0]];
}
void rotate(int x)
{
int old=fa[x],oldfa=fa[old],son=get(x);
ch[old][son]=ch[x][son^1],fa[ch[x][son^1]]=old;
fa[old]=x,ch[x][son^1]=old,fa[x]=oldfa;
if(oldfa)ch[oldfa][ch[oldfa][1]==old]=x;
update(x),update(old);return;
}
void splay(int x)
{
for(int f;f=fa[x];rotate(x))
if(fa[f])rotate(get(x)==get(f)?f:x);
root=x;
}
void insert(int x)
{
if(!root)
{
root=++sz;
cnt[root]=size[root]=1;
ch[root][1]=ch[root][0]=0;
key[root]=x;return;
}
int now=root,father=0;
while(1)
{
if(x==key[now])
{
cnt[now]++;
update(now),update(father);
splay(now);return;
}
father=now,now=ch[now][key[now]<x];
if(!now)
{
now=++sz;
cnt[now]=size[now]=1;
ch[now][1]=ch[now][0]=0;
key[now]=x;fa[now]=father;
ch[father][key[father]<x]=now;
update(father);splay(now);return;
}
}
}
int findx(int x)
{
int now=root;
while(1)
{
if(ch[now][0]&&x<=size[ch[now][0]])now=ch[now][0];
else
{
int tmp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
if(x<=tmp)return key[now];
x-=tmp;now=ch[now][1];
}
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
{
scanf("%d",&u[i]);
}
int lef=0;
for(int i=1;i<=m;i++)
{
while(lef<u[i])
{
insert(a[++lef]);
}
printf("%d\n",findx(i));
}
}