排队买票,但是 中途 出现插队情况,比如 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 <cstdio>
#include <iostream>
#include <algorithm>
#define lson L , m , rt << 1
#define rson m + 1 , R , rt << 1 | 1
using namespace std;
const int maxn = 240000;
struct Node
{
int L,R;
int sum;
}tree[maxn*4];
int p[maxn],val[maxn];
int n;
void builttree(int L,int R,int rt)
{
tree[rt].L=L;
tree[rt].R=R;
tree[rt].sum=R-L+1;
if(L==R)
return ;
int m=(L+R)/2;
builttree(lson);
builttree(rson);
}
int ans[maxn];
void Query(int rt,int pos,int val)
{
tree[rt].sum--;
if(tree[rt].L==tree[rt].R)
{
ans[tree[rt].L]=val;
return ;
}
int m=(tree[rt].L+tree[rt].R)/2;
if(tree[rt*2].sum>=pos)
Query(rt*2,pos,val);//左孩子可以容下则进左孩子
else
Query(rt*2+1,pos-tree[rt*2].sum,val);//左孩子已满
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d%d",&p[i],&val[i]);
builttree(1,n,1);
for(int i=n;i>=1;i--)
{
Query(1,p[i]+1,val[i]);
}
for(int i=1;i<=n;i++)
{
if(i==1)
printf("%d",ans[i]);
else
printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}