题目分析:就大致说一下怎么插入吧,伸展树的每个节点x保存以x为根的子树内优先级的最大值maxv,当寻找一个位置pos使得位置pos上的优先级小于待插入的节点的优先级且待插入节点的优先级小于位置pos+1上节点的优先级。找到这个pos,取pos = min { pos , 脸皮厚度,序列长度 },然后将待插入的节点插入到pos位置的后一个,可以将pos位置旋转到根,再将pos+1旋转到根的右节点,则pos的右节点的左节点就可以放新节点了。
本题注意因为有两个虚拟节点,且左边的那个一定会被计数,所以得到的位置应该减去左边的一个虚拟节点。
其他就没什么了,赤果果的伸展树啊。
代码如下:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define REP( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define REV( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
const int MAXN = 100005 ;
struct SplayNode {
int idx ;
int v ;
int s ;
int maxv ;
SplayNode* c[2] ;
SplayNode* f ;
SplayNode () : s ( 0 ) {}
void pushup () {
s = c[0] -> s + c[1] -> s + 1 ;
maxv = max ( v , max ( c[0] -> maxv , c[1] -> maxv ) ) ;
}
} Tnull , *null = &Tnull ;
struct Splay {
SplayNode node[MAXN] ;
SplayNode* cur ;
SplayNode* root ;
SplayNode* newnode ( int v , SplayNode* f , int idx = 0 ) {
cur -> idx = idx ;
cur -> v = v ;
cur -> maxv = v ;
cur -> s = 1 ;
cur -> f = f ;
cur -> c[0] = cur -> c[1] = null ;
return cur ++ ;
}
void clear () {
cur = node ;
root = newnode ( 0 , null ) ;
root -> c[1] = newnode ( 0 , root ) ;
root -> pushup () ;
}
void rotate ( SplayNode* o , int d ) {
SplayNode* p = o -> f ;
p -> c[!d] = o -> c[d] ;
o -> c[d] -> f = p ;
o -> f = p -> f ;
if ( p -> f != null ) {
if ( p == p -> f -> c[0] ) p -> f -> c[0] = o ;
else p -> f -> c[1] = o ;
}
o -> c[d] = p ;
p -> f = o ;
p -> pushup () ;
if ( p == root ) root = o ;
}
void splay ( SplayNode* o , SplayNode* f ) {
while ( o -> f != f ) {
SplayNode* p = o -> f ;
if ( p -> f == f ) {
if ( o == p -> c[0] ) rotate ( o , 1 ) ;
else rotate ( o , 0 ) ;
} else {
if ( p == p -> f -> c[0] ) {
if ( o == p -> c[0] ) rotate ( p , 1 ) , rotate ( o , 1 ) ;
else rotate ( o , 0 ) , rotate ( o , 1 ) ;
} else {
if ( o == p -> c[1] ) rotate ( p , 0 ) , rotate ( o , 0 ) ;
else rotate ( o , 1 ) , rotate ( o , 0 ) ;
}
}
}
o -> pushup () ;
}
void select ( int k , SplayNode* f ) {
SplayNode* o = root ;
++ k ;
while ( 1 ) {
int s = o -> c[0] -> s ;
if ( s + 1 == k ) break ;
if ( k <= s ) o = o -> c[0] ;
else {
k -= s + 1 ;
o = o -> c[1] ;
}
}
splay ( o , f ) ;
}
SplayNode* get ( int l , int r ) {
select ( l - 1 , null ) ;
select ( r + 1 , root ) ;
return root -> c[1] -> c[0] ;
}
void insert ( int pos , int v , int idx ) {
get ( pos + 1 , pos ) ;
SplayNode* o = newnode ( v , root -> c[1] , idx ) ;
root -> c[1] -> c[0] = o ;
root -> c[1] -> pushup () ;
root -> pushup () ;
}
int get_number ( int key ) {
SplayNode* o = root ;
int s = 0 ;
while ( o != null ) {
if ( o -> c[0] -> maxv > key ) o = o -> c[0] ;
else if ( o -> v > key ) {
s += o -> c[0] -> s ;
break ;
} else {
s += o -> c[0] -> s + 1 ;
o = o -> c[1] ;
}
}
return s - 1 ;
}
void show ( SplayNode* o ) {
if ( o -> c[1] ) show ( o -> c[1] ) ;
if ( o -> idx ) printf ( "%d " , o -> idx ) ;
if ( o -> c[0] ) show ( o -> c[0] ) ;
}
} T ;
int n ;
void solve () {
int ai , ci ;
int cnt = 0 ;
T.clear () ;
FOR ( i , 1 , n ) {
scanf ( "%d%d" , &ai , &ci ) ;
int pos = min ( min ( T.get_number ( ai ) , ci ) , cnt ) ;
T.insert ( pos , ai , i ) ;
++ cnt ;
}
T.show ( T.root ) ;
}
int main () {
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}