题意:一些人按顺序插队,给出每个人要插入的位置,求出最终的序列。
只要求出每个人的位置即可。观察发现,倘若有多个人要求插入到第一个人后面,那么这些人中的最后一个达成心愿,而倒数第二个人则会站到这个人身后。
既然如此,那我们只要按顺序从后向前处理。每个人(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'); } }