题意:
一共i次操作,每次操作将[i,第i小数所在位置]翻转,输出n个数字,每次翻转操作前第i小数所在位置
思路:
Splay伸展树维护权值并维护区间最小值和区间最小值所在位置,进行区间查询最小值和翻转区间操作,Splay树完成区间操作是先通过Splay操作将L-1Splay到树根,那么此时树根的右子树里面维护就是[l,n],然后将R+1Splay操作到树根的右子树上,那么此时树根右子树的左子树就是区间[L,R]的所有数了,此时你就可以对这个子树进行你想要的查询与修改
因为选定区间时需要先将L-1和R+1翻转到树根,但是L-1可能为0或者R+1可能为n+1这两个节点不存在,所以我们需要添加两个虚拟节点来防止这种越界的危险
至于最小值的维护和区间翻转的实现就具体看代码吧
另外此题可能会出现相同数字,我们需要提前处理一下
处理代码:
struct node
{
int val,pos;
friend bool operator<( const node&a , const node&b )
{
if ( a.val==b.val )
return a.pos<b.pos;
else
return a.val<b.val;
}
}data[maxn];
for ( int i=1 ; i<=n ; i++ )
scanf ( "%d" , &data[i].val ),data[i].pos = i;
sort ( data+1 , data+n+1 );
for ( int i=1 ; i<=n ; i++ )
a[data[i].pos+1] = i;
C++代码:
#include<map>
#include<set>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<complex>
#include<iostream>
#include<algorithm>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
typedef double DB;
typedef long long LL;
typedef complex<double>CD;
const int maxn = 100010;
const int mod = 1000000;
const int inf = 0x3f3f3f3f;
const int INF = 0x7FFFFFFF;
void Mod( int &x ){ x%=mod; }
int Min( int a , int b ){ return a<b?a:b; }
int Max( int a , int b ){ return a>b?a:b; }
int Abs( int x ){ return x>=0?x:-x; }
int Random(){ static int seed = 703; return seed=(int)(seed*48271LL%2147483647); }
int n,root,fa[maxn],sz[maxn],son[maxn][2],val[maxn];
int minx[maxn],minp[maxn],rev[maxn],ans[maxn],s[maxn],a[maxn];
struct node
{
int val,pos;
friend bool operator<( const node&a , const node&b )
{
if ( a.val==b.val )
return a.pos<b.pos;
else
return a.val<b.val;
}
}data[maxn];
void Update( int k )
{
int ls = son[k][0];
int rs = son[k][1];
minx[k] = val[k];
minp[k] = k;
if ( minx[ls]<minx[k] )
minx[k] = minx[ls],minp[k] = minp[ls];
if ( minx[rs]<minx[k] )
minx[k] = minx[rs],minp[k] = minp[rs];
sz[k] = sz[ls]+sz[rs]+1;
}
void Pushdown( int k )
{
int ls = son[k][0];
int rs = son[k][1];
rev[k] ^= 1;
rev[ls]^= 1;
rev[rs]^= 1;
swap ( son[k][0] , son[k][1] );
}
void Rotate( int x , int kind )
{
int y = fa[x];
int z = fa[y];
son[y][1-kind] = son[x][kind];
if ( son[x][kind]!=0 )
fa[son[x][kind]] = y;
fa[x] = z;
if ( z!=0 )
son[z][son[z][1]==y] = x;
fa[y] = x,son[x][kind] = y;
Update( y );
Update( x );
}
void Splay( int x , int ace )
{
int top = 0;
for ( int i=x ; i!=0 ; i=fa[i] )
s[++top] = i;
for ( int i=top ; i>=1 ; i-- )
if ( rev[s[i]] )
Pushdown( s[i] );
while ( fa[x]!=ace )
{
int y = fa[x];
int z = fa[y];
if ( z==ace )
Rotate( x , son[y][1]!=x );
else
{
if ( son[y][1]==x&&son[z][1]==y )
Rotate( y , 0 ),Rotate( x , 0 );
else if ( son[y][1]==x&&son[z][0]==y )
Rotate( x , 0 ),Rotate( x , 1 );
else if ( son[y][0]==x&&son[z][0]==y )
Rotate( y , 1 ),Rotate( x , 1 );
else
Rotate( x , 1 ),Rotate( x , 0 );
}
}
if ( ace==0 )
root = x;
}
void Build( int l , int r , int f )
{
if ( l>r )
return;
if ( l==r )
{
int now = l,pre = f;
fa[now] = pre;
if ( now<pre )
son[pre][0] = now;
else
son[pre][1] = now;
val[now] = a[now];
minx[now] = a[now];
minp[now] = now;
sz[now] = 1;
rev[now] = 0;
return;
}
int mid = (l+r)>>1,now = mid,pre = f;
Build ( l , mid-1 , mid );
Build ( mid+1 , r , mid );
fa[now] = pre;
val[now] = a[now];
minx[now] = a[now];
minp[now] = now;
Update( now );
if ( now<pre )
son[pre][0] = now;
else
son[pre][1] = now;
}
int Find( int k , int s )
{
if ( rev[k] )
Pushdown( k );
int ls = son[k][0];
int rs = son[k][1];
if ( s==sz[ls]+1 )
return k;
else if ( s<=sz[ls] )
return Find( ls , s );
else
return Find( rs , s-sz[ls]-1 );
}
int Query( int l , int r )
{
int x = Find ( root , l );
int y = Find ( root , r+2 );
Splay ( x , 0 );
Splay ( y , x );
int z = son[y][0];
return minp[z];
}
void Reverse( int l , int r )
{
int x = Find( root , l );
int y = Find( root , r+2 );
Splay ( x , 0 );
Splay ( y , x );
int z = son[y][0];
rev[z] ^= 1;
}
int main()
{
for ( ; scanf ( "%d" , &n )==1 ; )
{
a[1] = a[n+2] = minx[0] = inf;
for ( int i=1 ; i<=n ; i++ )
scanf ( "%d" , &data[i].val ),data[i].pos = i;
sort ( data+1 , data+n+1 );
for ( int i=1 ; i<=n ; i++ )
a[data[i].pos+1] = i;
Build ( 1 , n+2 , 0 );
root = ( n+3 )>>1;
for ( int i=1 ; i<=n ; i++ )
{
int x = Query ( i , n );
Splay ( x , 0 );
ans[i] = sz[son[x][0]];
Reverse( i , ans[i] );
}
printf ( "%d" , ans[1] );
for ( int i=2 ; i<=n ; i++ )
printf ( " %d" , ans[i] );
printf ( "\n" );
}
return 0;
}