排队买票,但是 中途 出现插队情况,比如 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>
#define N 200005
#include <stdio.h>
using namespace std;
struct Tree
{
int l,r;
int res;
}tree[N*4];
int ans[N];
void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
if(tree[root].l==tree[root].r)
{
tree[root].res=1;
return;
}
int mid=(r+l)/2;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
tree[root].res=tree[root<<1].res+tree[root<<1|1].res;
}
void query(int root,int pos,int val)
{
tree[root].res--;
if(tree[root].l==tree[root].r)
{
ans[tree[root].l]=val;
}
else
{
if(pos<=tree[root*2].res)
query(root*2,pos,val);
else
query(root*2+1,pos-tree[root*2].res,val);
}
}
struct sa
{
int p,v;
}data[N];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{ build(1,1,n);
for(int i=1;i<=n;i++)
scanf("%d%d",&data[i].p,&data[i].v);
for(int i=n;i>=1;i--)
query(1,data[i].p+1,data[i].v);
for(int i=1;i<n;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
return 0;
}