您的位置:首页 > 其它

BZOJ 1552: [Cerc2007]robotic sort( splay )

2015-06-16 14:37 465 查看


kpm大神说可以用块状链表写...但是我不会...写了个splay....

先离散化 , 然后splay结点加个min维护最小值 , 就可以了...

( ps BZOJ 3506 题意一样 , 双倍经验 )

-----------------------------------------------------------------------

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; ++i )#define clr( x , c ) memset( x , c , sizeof( x ) )#define Rep( i , n ) for( int i = 1 ; i <= n ; ++i ) using namespace std; const int maxn = 100000 + 5;const int maxnode = 101000;const int inf = 0x7fffffff; int n; struct data { int v , pos; bool operator < ( const data &rhs ) const { return ( v < rhs.v ) || ( v == rhs.v && pos < rhs.pos ); }}; bool cmp( const data &a , const data &b ) { return a.pos < b.pos;} data A[ maxn ]; struct Node *pt , *null; struct Node { Node *ch[ 2 ] , *p; int mn , val , size; bool rev; Node( int v = inf ) { mn = val = v; ch[ 0 ] = ch[ 1 ] = null; rev = 0; } inline void setc( Node* c , int d ) { ch[ d ] = c; c -> p = this; } inline bool d() { return this == p -> ch[ 1 ]; } inline void Rev() { rev ^= 1; } inline void upd() { size = ch[ 0 ] -> size + ch[ 1 ] -> size + 1; mn = min( val , min( ch[ 0 ] -> mn , ch[ 1 ] -> mn ) ); } inline void relax() { if( rev ) { swap( ch[ 0 ] , ch[ 1 ] ); rep( i , 2 ) if( ch[ i ] != null ) ch[ i ] -> Rev(); rev = 0; } } void* operator new( size_t ) { return pt++; }}; Node NODE[ maxnode ];Node* root; Node* build( int l , int r ) { if( l >= r ) return null; int m = ( l + r ) >> 1; Node* t = new Node( A[ m ].v ); t -> setc( build( l , m ) , 0 ); t -> setc( build( m + 1 , r ) , 1 ); t -> upd(); return t;} void rot( Node* t ) { Node* p = t -> p; p -> relax(); t -> relax(); int d = t -> d(); p -> p -> setc( t , p -> d() ); p -> setc( t -> ch[ ! d ] , d ); t -> setc( p , ! d ); p -> upd(); if( p == root ) root = t;} void splay( Node* t , Node* f = null ) { while( t -> p != f ) { if( t -> p -> p == f ) rot( t ); else if( t -> d() != t -> p -> d() ) rot( t ) , rot( t ); else rot( t -> p ) , rot( t ); } t -> upd();} Node* select( int k ) { for( Node* t = root ; ; ) { t -> relax(); int s = t -> ch[ 0 ] -> size; if( s == k ) return t; else if( s < k ) { k -= s + 1; t = t -> ch[ 1 ]; } else t = t -> ch[ 0 ]; }} int v;Node* find( Node* t ) { t -> relax(); if( t -> val == v ) return t; else return find( t -> ch[ 0 ] -> mn != v ? t -> ch[ 1 ] : t -> ch[ 0 ] );} Node* &get( int l , int r ) { l-- , r++; Node* L = select( l ); Node* R = select( r ); splay( L ); splay( R , L ); return R -> ch[ 0 ];} void init() { pt = NODE; null = new( Node ); null -> size = 0; root = build( 0 , n + 2 ); root -> p = null;} int main() { freopen( "test.in" , "r" , stdin ); cin >> n; Rep( i , n ) { scanf( "%d" , &A[ i ].v ); A[ i ].pos = i; } sort( A + 1 , A + n + 1 ); Rep( i , n ) A[ i ].v = i; sort( A + 1 , A + n + 1 , cmp ); A[ 0 ].v = A[ n + 1 ].v = inf; init(); Rep( i , n ) { v = i; Node* &t = get( i , n ); Node* x = find( t ); splay( x ); int k = x -> ch[ 0 ] -> size; printf( "%d" , k ); if( i != n ) printf( " " ); x = get( i , k ); x -> Rev(); splay( x ); } return 0;} -----------------------------------------------------------------------

1552: [Cerc2007]robotic sort

Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 486 Solved: 203
[Submit][Status][Discuss]

Description


Input

输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

Output

输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,(1 < = Pi < = N),Pi表示第i次操作前第i小的物品所在的位置。 注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

Sample Input

6
3 4 5 1 6 2

Sample Output

4 6 4 5 6 6

HINT

Source

HNOI2009集训Day6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: