#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int M=200005;
int seg[M<<2];//存区间的空位置数
int ans[M];//记录最终位置
void Push_Up(int rt)
{
seg[rt]=seg[rt<<1]+seg[rt<<1|1];
}
void build(int l,int r,int rt)
{
if(l==r)
{
seg[rt]=1;
return;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
Push_Up(rt);//左右儿子建完后 更新父节点
}
void update(int p,int v,int l,int r,int rt)
{
if(l==r)
{
ans[l]=v;
seg[rt]=0;
return;
}
int m=(l+r)>>1;
if(seg[rt<<1]>=p)
{
update(p,v,l,m,rt<<1);
}
else
{
update(p-seg[rt<<1],v,m+1,r,rt<<1|1);//p:整个线段的第p个空位
}
Push_Up(rt);
}
int main()
{
int p[M],v[M];
int n;
while(cin>>n)
{
build(1,n,1);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&p[i],&v[i]);
}
for(int i=n;i>=1;i--)//思路:最后一个人插入的位置后,该位置固定,所以则从后往前推出答案 ,pos为整个线段的第pos个空位
{
update(p[i]+1,v[i],1,n,1); //pos可以看做整个线段的第pos个空位
//则pos要么等于p(p为空时) 要么在大于p(p有人则往后走)
}
for(int i=1;i<=n;i++)
{
cout<<ans[i]<<" ";
}
cout<<endl;
}
return 0;
}
poj 2828 线段树(单点更新,逆序插入)
最新推荐文章于 2019-08-12 12:35:51 发布