题目描述:插队问题,可以用线段树和树状数组来解决。这里只给出线段树的做法,因为最后一个人要站的位置一定是他想站的位置,所以考虑逆序输入,假如他要站在n位置,有两种情况,(1)如果要站的位置在前一半就能够站的下,那么他就站在第n个空位上(2)否则,他要站的位置减去前一半被占满的人数,然后站在后一半。用线段树解即可。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define MAXN 200010
int Tree[MAXN*6],ans[MAXN],pos[MAXN],val[MAXN];
int n,id;
void build(int l,int r,int v)
{
Tree[v]=r-l+1;
if(l==r)
return;
int mid=(l+r)/2;
build(l,mid,v*2);
build(mid+1,r,v*2+1);
}
void update(int p,int l,int r,int v)
{
Tree[v]--;
if(l==r)
{
id=l;
return ;
}
int mid=(l+r)/2;
if(p<=Tree[v*2]) update(p,l,mid,v*2);
else
{
p-=Tree[v*2];
update(p,mid+1,r,v*2+1);
}
}
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
memset(pos,0,sizeof(pos));
memset(val,0,sizeof(val));
memset(Tree,0,sizeof(Tree));
build(1,n,1);
for(i=1;i<=n;i++)
{
scanf("%d%d",&pos[i],&val[i]);
}
for(i=n;i>=1;i--)
{
update(pos[i]+1,1,n,1);
ans[id]=val[i];
}
for(i=1;i<=n;i++)
{
if(i==1) printf("%d",ans[i]);
else
printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}