解题思路:
就是Splay的区间翻转操作。
加入两个虚拟节点0,n+1。
每次操作把0旋到root,k+1旋到son[root][1],那么son[son[root][1][0]这棵子树即是区间[1,k]了,打上翻转标记即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=300005;
int n,a[N];
int tot,root,son[N][2],val[N],fa[N],rev[N],size[N];
void build(int &u,int l,int r)
{
int mid=l+r>>1;
val[u=++tot]=a[mid];
if(l<mid)build(son[u][0],l,mid-1),fa[son[u][0]]=u;
if(mid<r)build(son[u][1],mid+1,r),fa[son[u][1]]=u;
size[u]=size[son[u][0]]+size[son[u][1]]+1;
}
int which(int x)
{
return son[fa[x]][1]==x;
}
void pushdown(int x)
{
if(rev[x])
{
swap(son[x][0],son[x][1]);
if(son[x][0])rev[son[x][0]]^=1;
if(son[x][1])rev[son[x][1]]^=1;
rev[x]=0;
}
}
void Rotate(int x)
{
int y=fa[x],z=fa[y],t=which(x);
pushdown(x),pushdown(y);
if(y==root)root=x;
else son[z][which(y)]=x;
fa[x]=z,fa[y]=x;
son[y][t]=son[x][t^1],son[x][t^1]=y;
if(son[y][t])fa[son[y][t]]=y;
size[x]=size[y],size[y]=size[son[y][0]]+size[son[y][1]]+1;
}
void Splay(int x,int f)
{
while(fa[x]!=f)
{
if(fa[fa[x]]!=f)
which(x)==which(fa[x])?Rotate(fa[x]):Rotate(x);
Rotate(x);
}
}
int find(int k)
{
int u=root;pushdown(u);
while(size[son[u][0]]!=k)
{
if(size[son[u][0]]>k)u=son[u][0];
else k-=size[son[u][0]]+1,u=son[u][1];
pushdown(u);
}
return u;
}
void Select(int k,int f)
{
int u=find(k);
Splay(u,f);
}
int main()
{
freopen("lx.in","r",stdin);
freopen("lx.out","w",stdout);
n=getint();
for(int i=1;i<=n;i++)a[i]=getint();
build(root,0,n+1);
int x=val[find(1)];
if(x==1){puts("0");return 0;}
Select(0,0);
for(int i=1;i<=100000;i++)
{
Select(x+1,root);
x=son[son[root][1]][0];
rev[x]^=1;
x=val[find(1)];
if(x==1){cout<<i<<'\n';return 0;}
}
puts("-1");
return 0;
}