题目描述:
题目分析:
首先排个序,求出每次找到最小的数是哪个,当然输出答案要记录size
搞个rev标记,注意下放!
题目链接:
Ac 代码:
#include<cstdio>
#include<algorithm>
#define il inline
using namespace std;
const int maxm=100010;
int n,top,ch[maxm][2],fa[maxm],num[maxm],a[maxm],siz[maxm],stk[maxm];
bool rev[maxm];
il bool comp(int x,int y)
{
return num[x]<num[y]||num[x]==num[y]&&x<y;
}
il bool pd(int x)
{
return x==ch[fa[x]][1];
}
il void update(int x)
{
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
il void down(int x)
{
if(!rev[x]) return;
swap(ch[x][0],ch[x][1]);
if(ch[x][0]) rev[ch[x][0]]^=1;
if(ch[x][1]) rev[ch[x][1]]^=1;
rev[x]=0;
}
il void up(int x,int y)
{
//printf("-%d-\n",top);
for(;;x=fa[x])
{
stk[++top]=x;
if(x==y) break;
}
while(top) down(stk[top--]);
}
il void rotate(int x)
{
int y=fa[x],z=pd(x);
ch[y][z]=ch[x][1-z];
if(ch[x][1-z]) fa[ch[x][1-z]]=y;
fa[x]=fa[y];
if(fa[y]) ch[fa[y]][pd(y)]=x;
ch[x][1-z]=y,fa[y]=x;
update(y),update(x);
}
il void splay(int x,int y)
{
up(x,y);
while(fa[x]!=y)
{
if(fa[fa[x]]!=y)
if(pd(x)==pd(fa[x])) rotate(fa[x]);
else rotate(x);
rotate(x);
}
update(x);
}
il void del(int x)
{
down(x);
int y=ch[x][1];
while(1)
{
down(y);
if(ch[y][0]) y=ch[y][0];
else break;
}
splay(y,0);
fa[ch[x][0]]=fa[x],ch[fa[x]][0]=ch[x][0];
update(fa[x]);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]),a[i]=i;
siz[i]=i,fa[i]=i+1,ch[i+1][0]=i;
}
siz[n+1]=n+1;
sort(a+1,a+n+1,comp);
for(int i=1;i<=n;i++)
{
splay(a[i],0);
printf("%d ",siz[ch[a[i]][0]]+i);
rev[ch[a[i]][0]]^=1;
del(a[i]);
}
return 0;
}