看完此题数据范围n<=100000,就知道与模拟无缘了(不知道是脑残还是怎样,第一次做的时候由于只剩下半个小时,于是匆匆写了个模拟,然后光荣的爆0了,原因很简单,我把题目看错了T_T)
就是这句话:如果有高度相同的物品,必须保证他们排序后与初始的相对位置关系相同。
被样例2骗了,SB的写了一个错误的DP,然后由于splay太长时间没写,所以……
对于这个限制条件,我给每个点加上了时间标记dnf(这当然不是tarjan……随手写写而已)
然后加上三个与DP相关的域:mi,ti,pos,分别表示当前区间可以取到的最小值、该最小值所对应的时间戳,要达到该最小值该怎么走(pos=0时为本身,pos=1时向左走,pos=2时向右走),然后DP方程就可以随便写了,另外涉及反转区间加上rev域,这个真是做烂了,没什么好说的。
好不容易把splay写完了,结果TLE(我开始质疑这台电脑了),无奈之下,将初始的链建成一棵二叉树,还是TLE,然后只好到bzoj上提交,两份代码都AC了,相差几十毫秒(坑爹啊!)
这一次偷懒没写自顶向下的splay,写的是自底向上的,感觉WJMZBMR的思路太神奇了,splay那么短(十分感动……)
其他就没有什么好说了,上代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <map>
#define setc(x,s,d) (p[c[x][d]=s]=x,update(x))
#define root(x) (!p[x])
#define ch(x) (c[p[x]][1]==x)
#define _rev(x) (rev[x]^=1)
#define MaxN 100010
using namespace std;
const int INF=~0U>>2;
int n,t,x,ans;
int a[MaxN],c[MaxN][2],p[MaxN],sz[MaxN];
int pos[MaxN],mi[MaxN],dfn[MaxN],ti[MaxN];
bool rev[MaxN];
map<int,int> m;
map<int,int>::iterator iter;
inline void push(const int &x)
{
if(!x) return;
if(rev[x])
{
swap(c[x][0],c[x][1]);
pos[x]=(3-pos[x])%3;
if(c[x][0]) _rev(c[x][0]);
if(c[x][1]) _rev(c[x][1]);
rev[x]=0;
}
}
inline void update(const int &x)
{
if(!x) return;
sz[x]=sz[c[x][0]]+1+sz[c[x][1]];
mi[x]=a[x],pos[x]=0,ti[x]=dfn[x];
for(int i=0;i<2;i++)
if(mi[c[x][i]]<mi[x])
mi[x]=mi[c[x][i]],
pos[x]=i+1,
ti[x]=ti[c[x][i]];
else if(mi[c[x][i]]==mi[x])
if(ti[c[x][i]]<ti[x])
pos[x]=i+1,
ti[x]=ti[c[x][i]];
}
inline void rorate(const int &x)
{
int f=p[x];
bool d=ch(x);
setc(f,c[x][!d],d);
if(root(f)) p[x]=p[f];
else setc(p[f],x,ch(f));
setc(x,f,!d);
}
inline int find(int &t)
{
int ans=0;
push(t);
while(pos[t])
{
if(pos[t]-1) ans+=sz[c[t][0]]+1;
t=c[t][pos[t]-1];
push(t);
}
return ans+sz[c[t][0]];
}
inline void splay(int rt,int x)
{
while(p[x]!=rt)
if(p[p[x]]==rt)
rorate(x);
else if(ch(x)==ch(p[x]))
rorate(p[x]),rorate(x);
else rorate(x),rorate(x);
}
inline int side(int x)
{
push(x);
while(c[x][0])
x=c[x][0],
push(x);
return x;
}
inline void work()
{
for(int i=1;i<n;i++)
{
x=t;
ans=find(x);
printf("%d ",ans+i);
splay(0,x);
splay(x,side(c[x][1])),
t=c[x][1],
setc(t,c[x][0],0),
_rev(c[x][0]);
p[t]=0;
}
printf("%d\n",n);
}
int build(int l,int r)
{
if(l>r) return 0;
int m=(l+r)>>1;
if(l!=r)
p[c[m][0]=build(l,m-1)]=m,
p[c[m][1]=build(m+1,r)]=m;
update(m);
return m;
}
inline void init()
{
cin>>n;
mi[0]=dfn[0]=ti[0]=INF;
a[n+1]=mi[n+1]=dfn[n+1]=ti[n+1]=INF;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
iter=m.find(a[i]);
if(iter==m.end())
m.insert(make_pair(a[i],0));
else dfn[i]=++(iter->second);
// setc(i,i-1,0);
}
t=build(1,n+1);
// t=n;
}
int main()
{
freopen("sort.in","r",stdin);
freopen("sort.out","w",stdout);
init();
work();
return 0;
}