思路:
从后往前推,那么最后一个人肯定能在他想的位置上,倒数第二个人时,对与他来说当时只有i-1个人 他要在pos【i】个人的后面,那么找出除去倒数第一个人的第pos【i】+1个空位在哪即可
那么num【root】表示l到r还有几个空位,每次找出第pos【i】+1个空位在哪即可
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int id[200100];
int pos[200100], val[200100];
int num[810000];
int N;
int lc( int root ){
return root * 2;
}
int rc( int root ){
return root * 2 + 1;
}
void updata( int root ){
num[root] = num[lc(root)] + num[rc(root)];
}
void built( int l, int r, int root ){
if( l == r ){
num[root] = 1;
return;
}
int mid = ( l + r ) / 2;
built( l, mid, lc( root ) );
built( mid + 1, r, rc( root ) );
updata( root );
return;
}
int query( int pos, int l, int r, int root ){
if( l == r ){
num[root] = 0;
return l;
}
int mid = ( l + r ) / 2;
int ans;
if( num[lc(root)] >= pos ){
ans = query( pos, l, mid, lc( root ) );
}else{
ans = query( pos - num[lc(root)], mid + 1, r, rc( root ) );
}
updata( root );
return ans;
}
int main(){
while( scanf( "%d", &N ) != EOF ){
for( int i = 1; i <= N; i++ ){
scanf( "%d%d", &pos[i], &val[i] );
}
built( 1, N, 1 );
for( int i = N; i >= 1; i-- ){
int temp = query( pos[i] + 1, 1, N, 1 );
id[temp] = i;
}
cout << val[id[1]];
for( int i = 2; i <= N; i++ ){
cout << " " << val[id[i]];
}
cout << endl;
}
return 0;
}