// http://www.cnblogs.com/shenben/p/5624886.html
// 思路:根据题目可知,最后插入的位置的数才是最终不变的数,
// 所以可以从最后的输入作第1个放入,依此类推,倒插入。
// 在插入时也有一定的技术,首先创建一棵空线段树时,每个节点
// 记录当前范围内有多少个空位置。在插入时,要注意,一个数放
// 入之后那么这个位置就不用管了,那么树中所有的空位置就是余
// 下的数所对应的位置,也就是把余下的数又可以看作是一个新的
// 集合。那么每次插入都是当前集合的第1次放。
#include<iostream>
#include<cstdio>
using namespace std;
const int N=200005;
int n,id,pos[N],val[N],ans[N],w[N*3];
void build(int k,int left,int right){
w[k]=right-left+1; // w记录这个区间有多少的空位。
int mid=(left+right>>1);
if(left<right){
build(k<<1,left,mid);
build(k<<1|1,mid+1,right);
}
}
void updata(int k,int pos,int l,int r){
w[k]--;// 这个区间增加了一人,区间空位-1。
if(l==r){
id=l;return;
}
int mid=(l+r)/2;
if(w[k<<1]>=pos) updata(k<<1,pos,l,mid);
else{
pos-=w[k<<1];
updata(k<<1|1,pos,mid+1,r);
}
}
int main(){
freopen("a.txt","r",stdin);
while(scanf("%d",&n)==1){
build(1,1,n);
for(int i=1;i<=n;i++)
scanf("%d%d",&pos[i],&val[i]);
for(int i=n;i>=1;i--){
updata(1,pos[i]+1,1,n);
ans[id]=val[i];
}
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
putchar('\n');
}
return 0;
}
07-23
1万+

08-08
1256
