题意:一些人按顺序插队,给出每个人要插入的位置,求出最终的序列。
只要求出每个人的位置即可。观察发现,倘若有多个人要求插入到第一个人后面,那么这些人中的最后一个达成心愿,而倒数第二个人则会站到这个人身后。
既然如此,那我们只要按顺序从后向前处理。每个人(Val)最终的位置就是此时第(Pos+1)个空位。
我们可以用线段树来完成每次的插入。每个节点保存区间剩余空位数,每次二分查找并修改第(Pos+1)个空位。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=200010;
struct node{
int res,L,R;
} tree[maxn<<2];
struct per{
int pos,val;
} a[maxn];
int ans[maxn],n;
void build(int p,int L,int R){
tree[p].L=L;tree[p].R=R;
tree[p].res=R-L+1;
if(L==R)return;
int mid=L+R>>1;
build(p<<1,L,mid);
build(p<<1|1,mid+1,R);
}
void add(int p,int pos,int val){
tree[p].res--;
if(tree[p].L==tree[p].R){
ans[tree[p].L]=val;
}
else{
if(pos <= tree[p<<1].res)add(p<<1,pos,val);
else add(p<<1|1,pos-tree[p<<1].res,val);
}
}
int main(){
while(~scanf("%d",&n)){
build(1,1,n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].pos,&a[i].val);
}
for(int i=n;i>=1;i--){
add(1,a[i].pos+1,a[i].val);
}
for(int i=1;i<=n;i++)
printf("%d%c",ans[i],i<n?' ':'\n');
}
}