题目大意: 现在要买票了,但是有人插队,每个人都有一个自己的属性值,问插队之后他们的属性值的排列顺序。
思路:逆序读入,每个结点的值代表还有的空格,一个萝卜一个坑,从后面开始,每个人插队的位置就是他的最终位置。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 200005
int a[maxn<<2],b[maxn<<2];
void build(int l,int r,int rt){
a[rt]=1;
if(l==r)
return ;
int mid=(l+r)/2;
build(l,mid,rt*2);
build(mid+1,r,rt*2+1);
a[rt]=a[rt*2]+a[rt*2+1];
}
void update(int x,int v,int l,int r,int rt){
if(l==r){
b[l]=v;
a[rt]=0;
return ;
}
int mid=(l+r)/2;
if(x<=a[rt*2]) update(x,v,l,mid,rt*2);
else update(x-a[rt*2],v,mid+1,r,rt*2+1);/*/若左子树的空格数大于等于要放入的位置,则搜索左子树;
否则,搜索右子树,由于左边有一些空位置,只需要搜索
右子树的部分空位置,使左右空位置之和为要搜索的位置。/*/
a[rt]=a[rt*2]+a[rt*2+1];
}
int main(){
int n,m[maxn],p[maxn];
while((scanf("%d",&n))!=EOF){
build(1,n,1);
for(int i=1;i<=n;i++)
scanf("%d%d",&p[i],&m[i]);
for(int i=n;i>0;i--)
update(p[i]+1,m[i],1,n,1);//逆序读入
for(int i=1;i<=n-1;i++)
printf("%d ",b[i]);
printf("%d\n",b[n]);
}
return 0;
}