题意:很多人(1~200000)在后半夜还在排队,由于天太黑,人们即使插队也不会被人发现,每个人的名字由一个整数代表([0, 32767] )。现在一次给出每个人插入的位置,(0代表第一个,1代表第二个。。。),计算N个人插入队后,队中各个位置都是谁。
分析:正向思考的话,这道题就是最简单的模拟了,传统的双层O(n*n),达到了4*10^10 , 计算机每秒处理复杂度的效率在10^8左右,呃。。 4S必然不够。。。 - -
分析:正向思考的话,这道题就是最简单的模拟了,传统的双层O(n*n),达到了4*10^10 , 计算机每秒处理复杂度的效率在10^8左右,呃。。 4S必然不够。。。 - -
每个节点除了左右区间外,再存储一下当前节点区间剩余的位置数量,那么一个人的位置表示的是他前面的人的数量,而先进队的人往往会被后来者挤到后面去,所以我们从后往前考虑,这样只要去找到那个包含该数量的区间,然后把这人放进去就可以了。
//8684K 1485MS
#include <stdio.h>
#define MAX 200010
#define MID(X,Y) (((X)+(Y))>>1)
#define L(X) (X<<1)
#define R(X) ((X<<1)|1)
struct node
{
int weight ;
int left , right ;
}node[MAX<<2];
int index ;
int pos[MAX],val[MAX] ;
int ans[MAX] ;
void Build_Tree ( int const left , int const n , int const right )
{
node[n].left = left ;
node[n].right = right ;
node[n].weight = right - left + 1 ;
if ( left < right )
{
int mid ;
mid = MID(left , right ) ;
Build_Tree ( left , L(n) , mid ) ;
Build_Tree ( mid + 1 , R(n) , right ) ;
}
}
void Update ( int pre , int const n )
{
node[n].weight -- ;
if ( node[n].right == node[n].left )
{
index = node[n].left ;
return ;
}
else
{
if ( pre <= node[L(n)].weight )
{
Update ( pre , L(n) ) ;
}
else
{
pre -= node[L(n)].weight ;
Update ( pre , R(n)) ;
}
}
}
int
main ( )
{
int n ;
while ( EOF != scanf ("%d" , & n ) )
{
Build_Tree ( 1 , 1 , n ) ;
int i ;
for ( i = 1 ; i <= n ; i ++ )
{
scanf ("%d%d" , &pos[i] , &val[i] ) ;
}
for ( i = n ; i >= 1 ; i -- )
{
Update ( pos[i] + 1 , 1 ) ;
ans[index] = val[i] ;
}
for ( i = 1 ; i <= n ; i ++ )
{
if ( i != n )
{
printf ("%d " , ans[i] ) ;
}
else
{
printf ("%d\n" , ans[i] ) ;
}
}
}
return 0 ;
}