排队买票,但是 中途 出现插队情况,比如 0 123,代表值为123的人 插入到 0 的位置,如果后面 出现 0 456,那么新的 0的位置就是 456,123就变成是 1的位置了
观察发现,最后一个插入到该位置的人位置是固定的,那么我们可以从后面进行插入操作,pos val 代表val要插入到pos位置,那么就是说 pos 前面要留出 pos个位置,
因为 是从 0 开始的。
线段树 :res 记录 该区间 目前还剩 res个空位,每一次 query即插入的时候 ,如果 该节点左儿子 res >=pos,那么只要在左儿子找就可以了
否则 要在右儿子中 找 ,此时 pos 改为 pos-左儿子res。。
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 200005
#define lson u<<1
#define rson u<<1|1
struct In{
int p,v;
}dat[MAXN];
int ans[MAXN];
struct Node{
int lef,rig;
int res;//记录当前区间有多少空位
}T[MAXN<<2];
void Build(int u,int l,int r){
T[u].lef=l;
T[u].rig=r;
if(l==r){T[u].res=1;return;}
int mid=(l+r)>>1;
Build(lson,l,mid);
Build(rson,mid+1,r);
T[u].res=T[lson].res+T[rson].res;
}
void Query(int u,int pos,int val){
T[u].res--;
if(T[u].lef==T[u].rig){
ans[T[u].lef]=val;
}
else {
if(pos<=T[lson].res)Query(lson,pos,val);
else Query(rson,pos-T[lson].res,val);
}
}
int main(){
int N,i;
while(scanf("%d",&N)==1){
Build(1,1,N);
//printf("u %d\n",T[1].res);
for(i=1;i<=N;i++)scanf("%d%d",&dat[i].p,&dat[i].v);
for(i=N;i>=1;i--)Query(1,dat[i].p+1,dat[i].v);
for(i=1;i<=N;i++){
printf("%d%c",ans[i],i<N?' ':'\n');
}
}
}