题目大意
解题思路
先按val为第一关键字,编号为第二关键字,从小到大排序,离散化。然后在末尾加入一个无穷大,建一棵splay,维护size和min的编号,支持求后继和区间翻转。
时刻保持上一个翻转的点为根,将将要翻转的挂在根下面,把将要翻转的的后继挂在根下面,然后对其左子树区间翻转。由于将要翻转的一定在其左子树的最右边,编号就是左子树的size加根及其左子树的点数。
code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define Min(a,b) ((a<b)?a:b)
#define Max(a,b) ((a>b)?a:b)
#define Fo(i,j,k) for(int i=j;i<=k;i++)
#define Fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const Mxn=1e5;
int N,Val[Mxn+9],Size[Mxn+9],Mi[Mxn+9],Swap[Mxn+9],Fa[Mxn+9],Son[Mxn+9][2]
,A[Mxn+9];
void Retag(int Now){
if(Now&&Swap[Now]){
swap(Son[Now][0],Son[Now][1]);
Swap[Son[Now][0]]^=1;
Swap[Son[Now][1]]^=1;
Swap[Now]=0;
}
}
int Side(int Now,int F){
return Son[F][1]==Now;
}
void Update(int Now){
Size[Now]=Size[Son[Now][0]]+Size[Son[Now][1]]+1;
Mi[Now]=(Val[Now]<=Val[Mi[Son[Now][0]]])?Now:Mi[Son[Now][0]];
Mi[Now]=(Val[Mi[Now]]<=Val[Mi[Son[Now][1]]])?Mi[Now]:Mi[Son[Now][1]];
}
void Rotate(int Now){
Retag(Now);
int F=Fa[Now],T=Side(Now,F);
Son[F][T]=Son[Now][!T];
Fa[Son[Now][!T]]=F;
Son[Fa[F]][Side(F,Fa[F])]=Now;
Fa[Now]=Fa[F];
Son[Now][!T]=F;
Fa[F]=Now;
Update(F);
Update(Now);
}
void Splay(int Now,int Top){
while(Fa[Now]!=Top){
if(Fa[Fa[Now]]==Top)Retag(Fa[Now]),Rotate(Now);
else{
Retag(Fa[Fa[Now]]),Retag(Fa[Now]);
if(Side(Now,Fa[Now])==Side(Fa[Now],Fa[Fa[Now]]))
Rotate(Fa[Now]),Rotate(Now);
else Rotate(Now),Rotate(Now);
}
}
}
int Next(int Now){
Retag(Now);Now=Son[Now][1];Retag(Now);
while(Son[Now][0]){
Now=Son[Now][0];
Retag(Now);
}
return Now;
}
bool Cmp(int X,int Y){return (Val[X]<Val[Y])||((Val[X]==Val[Y])&&(X<Y));}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d",&N);
Fo(i,1,N){
scanf("%d",&Val[i]),A[i]=i;
Fa[i]=i-1;
Son[i-1][1]=i;
}
sort(A+1,A+N+1,Cmp);
Fo(i,1,N)Val[A[i]]=i;
Fa[N+1]=N;
Son[N][1]=N+1;Mi[N+1]=N+1;Size[N+1]=1;
Val[0]=Val[N+1]=1e9;
Fd(i,N,1)Mi[i]=(Val[i]<Val[Mi[i+1]])?i:Mi[i+1],Size[i]=Size[i+1]+1;
printf("%d ",Mi[1]);
int Tmp,Pre,Now;
Splay(Tmp=Son[Pre=Mi[1]][1],0);
Swap[Son[Tmp][0]]^=1;
Fo(i,1,N-2){
Splay(Pre,0);
Splay(Now=Mi[Son[Pre][1]],Pre);
Splay(Tmp=Next(Now),Pre);
printf("%d ",N+1-Size[Tmp]+Size[Son[Tmp][0]]);
Swap[Son[Tmp][0]]^=1;
Pre=Now;
}
printf("%d ",N);
return 0;
}