比较裸的线段树,主要在能不能想到(。ì _ í。)
/*
思路:
设当前节点为root,其左孩子为lchild,右孩子为rchild,节点的存放变量为val,待插入数值为value.
1、建立线段树。每个结点存放其所在范围的还能存放的数值的个数
2、更新线段树。
(1、)root为线段树叶子结点。
(2、)position(value)<=lchild.val,则更新左孩子;否则position(value)-=lchild.val,更新右孩子。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int pos[200010];
int val[200010];
int f[200010];
int index;
struct SegTreeNode
{
int Val;//结点所在的范围内还能够存放几个数
}SegTree[200010<<2];
/*
作用:建立线段树
root:节点编号
[Begin, End]:结点表示的范围
*/
void creat(int root, int Begin, int End)
{
if(Begin == End)
{
SegTree[root].Val = End-Begin+1;
return ;
}
int mid = (Begin+End)>>1;
creat(root<<1, Begin, mid);
creat(root<<1|1, mid+1, End);
SegTree[root].Val = SegTree[root<<1].Val+SegTree[root<<1|1].Val;
}
/*
作用:更新线段树
root:结点编号
[Begin, End]:结点表示的范围
pos:插入value的位置
*/
void Update(int root, int Begin, int End, int pos)
{
SegTree[root].Val--;
if(Begin == End)
{
index = Begin;
return;
}
int mid = (Begin+End)>>1;
if(pos<=SegTree[root<<1].Val)
{
Update(root<<1,Begin, mid, pos);
}
else
{
pos-=SegTree[root<<1].Val;
Update(root<<1|1, mid+1, End, pos);
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
creat(1,1,n);
for(int i=1;i<=n;i++)
{
scanf("%d %d",&pos[i],&val[i]);
pos[i]+=1;
}
for(int j=n;j>=1;j--)
{
Update(1,1,n,pos[j]);
f[index] = val[j];
}
for(int i=1;i<=n;i++)
printf(i!=n?"%d ":"%d\n",f[i]);
}
return 0;
}