这是很裸的splay吗…..维护一下最小值和最小值是哪个点,因为对于当前处理的 ai , a1——ai−1 都已经按照顺序排好了,所以在 (i,n) 区间找到最小的那个点,然后就是splay的常规操作(旋上去,区间取反什么的)
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<ctime>
#include<cmath>
#include<vector>
#include<string>
#include<bitset>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 210000;
int tr[maxn][2],c[maxn],mn[maxn],rev[maxn],fa[maxn],md[maxn];
int num[maxn];
int root,n;
int a[maxn];
int sta[maxn],tp;
void reverse( int x )
{
rev[x] ^= 1;
swap( tr[x][0],tr[x][1] );
}
void pushdown( int x )
{
if( rev[x] )
{
rev[x] ^= 1;
if( tr[x][0] ) reverse( tr[x][0] );
if( tr[x][1] ) reverse( tr[x][1] );
}
}
void push_up( int x )
{
int lc=tr[x][0], rc=tr[x][1];
mn[x] = c[x]; md[x] = x;
if( lc && mn[lc] < mn[x] ) { mn[x] = mn[lc]; md[x] = md[lc]; }
if( rc && mn[rc] < mn[x] ) { mn[x] = mn[rc]; md[x] = md[rc]; }
num[x] = num[lc]+num[rc] +1;
}
void rotate( int x,int &k )
{
int y = fa[x], z = fa[y];
if( y == k ) k = x;
else tr[z][tr[z][1]==y] = x;
fa[x] = z;
int l = tr[y][1]==x,r=1^l;
fa[tr[x][r]] = y; fa[y] = x;
tr[y][l] = tr[x][r]; tr[x][r] = y;
push_up( y );
}
void splay( int x,int &k )
{
tp = 0;
for( int now=x;now!=k;now=fa[now] )
sta[++tp] = now;
sta[++tp] = k;
while( tp ) pushdown( sta[tp--] );
while( x != k )
{
int y = fa[x], z = fa[y];
if( y != k )
{
if( ( tr[y][0] == x )^( tr[z][0] == y ) ) rotate( x,k );
else rotate( y,k );
}
rotate( x,k );
}
push_up( x );
}
int build_( int l,int r,int f )
{
if( l > r ) return 0;
int x = (l+r)>>1; fa[x] = f;
mn[x] = c[x] = a[x];
md[x] = x;
num[x] = 1;
if( l == r ) return x;
int mid = (l+r)>>1;
tr[x][0] = build_( l,mid-1,x );
tr[x][1] = build_( mid+1,r,x );
push_up( x );
return x;
}
int find_( int x,int k )
{
pushdown( x );
int ls = num[tr[x][0]];
if( k <= ls ) return find_( tr[x][0],k );
else if( k == ls+1 ) return x;
else return find_( tr[x][1],k-ls-1 );
}
int f_min( int l,int r )
{
int t1 = find_( root,l ), t2 = find_( root,r+2 );
splay( t1,root ); splay( t2,tr[root][1] );
return md[tr[t2][0]];
}
void rever( int l,int r )
{
int t1 = find_( root,l ), t2 = find_( root,r+2 );
splay( t1,root ); splay( t2,tr[root][1] );
reverse( tr[t2][0] );
}
struct R
{
int pos,val;
}rd[maxn];
bool cmp( R x,R y )
{
return x.val == y.val ? x.pos < y.pos : x.val < y.val;
}
bool cmp2( R x,R y )
{
return x.pos < y.pos;
}
int main()
{
mn[0] = 99999; num[0] = 0;
scanf("%d",&n);
for( int i=1;i<=n;i++ )
{
scanf("%d",&rd[i].val);
rd[i].pos = i;
}
sort( rd+1,rd+n+1,cmp );
for( int i=1;i<=n;i++ ) rd[i].val = i;
sort( rd+1,rd+n+1,cmp2 );
for( int i=1;i<=n;i++ )
a[i+1] = rd[i].val;
a[1] = 99999;
a[n+2] = 99999;
build_( 1,n+2,0 ); root = (n+3)>>1;
for( int i=1;i<=n;i++ )
{
int l = f_min( i,n );
splay( l,root );
printf("%d",num[tr[l][0]]);
rever( i,num[tr[l][0]] );
if( i != n ) printf(" ");
}
return 0;
}