因为后面的人会影响去前面人的位置,(如果后面的人插在前面的人的位置,那么前面的人的位置就会向后移动),那么我们从后往前插入处理,这样保证插入后不会变化。用线段树的每个节点记录这个区间的空位置数,每次插入的时候将这个人放在第pos[i]个空格的地方, 因为后面的人如果排在前面人的前面,那么我们对前面的人进行操作的时候.那个位置就被占了,前面的人的位置就会向后移一格。这样,我们就可以用线段树进行维护了,每次查询第pos[i]个空格的位置,然后再改变表示pos[i]位置的节点状态。
该线段树中每个节点的状态值为所代表的区间的空位置数,初始化为区间长度。
#include<cstdio>
using namespace std;
const int maxn=2e5+10;
int tree[maxn<<2];
int id,ans[maxn],pos[maxn],val[maxn];
void build(int l,int r,int i){
tree[i]=r-l+1;
if(l==r) return ;
int mid=((l+r)>>1);
build(l,mid,i<<1);
build(mid+1,r,i<<1|1);
}
void update(int p,int l,int r,int i){
tree[i]--;
if(l==r){
id=l;
return;
}
int mid=((l+r)>>1);
if(tree[i<<1]>=p){
update(p,l,mid,i<<1);
}else{
p-=tree[i<<1];
update(p,mid+1,r,i<<1|1);
}
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
build(1,n,1);
for(int i=1;i<=n;i++){
scanf("%d%d",&pos[i],&val[i]);
}
for(int i=n;i>=1;i--){
update(pos[i]+1,1,n,1);
ans[id]=val[i];
}
printf("%d",ans[1]);
for(int i=2;i<=n;i++){
printf(" %d",ans[i]);
}
puts("");
}
return 0;
}