splay裸题不解释。。。
按照位置为关键字排序,维护子树大小和区间最小。
之后每找到一个最小的值,就把它区间旋到边上,然后放到最顶上扔掉
写得相对比较优美
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(x,y) (x<y?x:y)
using namespace std;
int n,i,j,k,l;
int a[100002];
int b[100002];
int c[100002];
int ch[100002][2];
int f[100002];
int s[100002];
int m[100002];
bool rev[100002];
void qsort(int l,int r)
{
int i,j,k,mid,mid2;
i=l;
j=r;
mid=b[(l+r)/2];
mid2=c[(l+r)/2];
while (i<=j)
{
while ((b[i]<mid) || ((b[i]==mid) && (c[i]<mid2))) i++;
while ((b[j]>mid) || ((b[j]==mid) && (c[j]>mid2))) j--;
if (i<=j)
{
k=b[i];
b[i]=b[j];
b[j]=k;
k=c[i];
c[i]=c[j];
c[j]=k;
i++;
j--;
}
}
if (l<j)
qsort(l,j);
if (i<r)
qsort(i,r);
return ;
}
void update(int t)
{
s[t]=1+s[ch[t][0]]+s[ch[t][1]];
m[t]=min(min(m[ch[t][0]],m[ch[t][1]]),a[t]);
}
void downtag(int t)
{
if (rev[t])
{
int i=ch[t][0];
ch[t][0]=ch[t][1];
ch[t][1]=i;
rev[ch[t][0]]^=1,rev[ch[t][1]]^=1,rev[t]=0;
}
}
void maketree(int t,int l,int r)
{
int mid=(l+r)/2;
if (l!=r)
{
if (l<mid)
maketree(mid,l,mid-1);
else
ch[mid][0]=n+1;
if (mid<r)
maketree(mid,mid+1,r);
}
f[mid]=t;
if (!ch[t][0])
ch[t][0]=mid;
else
ch[t][1]=mid;
update(mid);
}
void rot(int t)
{
downtag(t);
int x=(ch[f[t]][0]==t)?0:1;
f[ch[t][x^1]]=f[t],ch[f[t]][x]=ch[t][x^1];
ch[t][x^1]=f[t];
if ((f[f[t]]) && (ch[f[f[t]]][0]==f[t])) ch[f[f[t]]][0]=t; else ch[f[f[t]]][1]=t;
f[t]=f[f[t]],f[ch[t][x^1]]=t;
update(ch[t][x^1]),update(t);
}
void splay(int t,int x)
{
while (f[t]!=x)
{
if (f[f[t]]==x)
rot(t);
else
{
if ((ch[f[f[t]]][0]==f[t])^(ch[f[t]][0]==t))
rot(t),rot(t);
else
rot(f[t]),rot(t);
}
}
}
void find(int t,int sum,bool bz)
{
downtag(t);
if (a[t]==m[t])
{
if (i==1)
sum--;
if (bz)
printf("%d ",sum+1+s[ch[t][0]]),k=t;
splay(t,j);
return;
}
if (m[ch[t][0]]<m[ch[t][1]])
find(ch[t][0],sum,bz);
else
find(ch[t][1],sum+s[ch[t][0]]+1,bz);
}
int main()
{
memset(m,127,sizeof(m));
scanf("%d",&n);
fo(i,1,n)
scanf("%d",&a[i]),b[i]=a[i],c[i]=i;
qsort(1,n);
fo(i,1,n)
a[c[i]]=i;
maketree(0,1,n);
fo(i,1,n)
if (ch[i][0]>n)
ch[i][0]=0;
ch[0][0]=0;
ch[0][1]=(1+n)/2;
f[ch[0][1]]=0;
j=0;
fo(i,1,n-1)
{
downtag(ch[j][1]);
find(ch[j][1],s[ch[j][0]]+1,1);
if (ch[ch[j][1]][1])
{
l=ch[ch[j][1]][1];
downtag(l);
while (ch[l][0])
l=ch[l][0],downtag(l);
splay(l,j);
rev[k]=1;
}
else
rev[k]=1;
splay(k,0);
j=k;
}
printf("%d\n",n);
return 0;
}