对于大神来说这题是水题。我搞这题花了快2天。
伸展树的优点有什么,就是树不管你怎么旋转序列是不会改变得,并且你要使区间反转,只要把第k大的点转到根结点,那么它的左子树就是要交换的区间[l,r),然后交换左右
子树就可以了(中序),根结点的位置就是i+siz[ch[root][0]],i是处理完的结点个数,siz[ch[root][0]]就是左子树(需要旋转的个数)。 旋转可以用lazy思想标记,这样时间就为logn了。由于第k大的值已经处理完成,所以直接将根结点删除。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define key_value ch[ch[root][1]][0]
using namespace std;
const int MAXN = ;
struct node
{
int id;
int v;
}a[MAXN];
int pre[MAXN],ch[MAXN][],siz[MAXN],lazy[MAXN],tot1,root;
int s[MAXN],tot2,n;
bool cmp(node fa,node fb)
{
if(fa.v != fb.v)
return fa.v < fb.v;
return fa.id < fb.id;
}
void Treavel(int x)
{
if(x)
{
Treavel(ch[x][]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,lazy=%2d\n",x,ch[x][],ch[x][],pre[x],siz[x],lazy[x]);
Treavel(ch[x][]);
}
}
void debug()
{
printf("root:%d\n",root);
Treavel(root);
}
void Newnode(int &rt,int pa,int k)
{
rt = k;
pre[rt] = pa;
siz[rt] = ;
lazy[rt] = ;
ch[rt][] = ch[rt][] = ;
}
void pushup(int rt)
{
siz[rt] = siz[ch[rt][]] + siz[ch[rt][]] + ;
}
void pushdown(int rt)
{
if(lazy[rt]){
lazy[ch[rt][]] ^= ;
lazy[ch[rt][]] ^= ;
swap(ch[rt][],ch[rt][]);
lazy[rt] = ;
}
}
void build(int &rt,int l,int r,int pa)
{
if(l > r){
return ;
}
int m = (l+r)/;
Newnode(rt,pa,m);
build(ch[rt][],l,m-,rt);
build(ch[rt][],m+,r,rt);
pushup(rt);
}
void Init()
{
root = tot1 = tot2 = ;
ch[root][] = ch[root][] = siz[root] = lazy[root] = pre[root] = ;
build(root,,n,);
pushup(root);
}
void Rotate(int rt,int kind)
{
pushdown(pre[rt]);
pushdown(rt);
int y = pre[rt];
ch[y][!kind] = ch[rt][kind];
pre[ch[rt][kind]] = y;
if(pre[y]){
ch[pre[y]][ch[pre[y]][]==y] = rt;
}
pre[rt] = pre[y];
ch[rt][kind] = y;
pre[y] = rt;
pushup(y);
pushup(rt);
}
void splay(int rt,int goal)
{
pushdown(rt);
while(pre[rt] != goal)
{
if(pre[pre[rt]] == goal){
pushdown(pre[rt]);
pushdown(rt);
Rotate(rt,ch[pre[rt]][]==rt);
}
else {
pushdown(pre[pre[rt]]);
pushdown(pre[rt]);
pushdown(rt);
int y = pre[rt];
int kind = ch[pre[y]][]==y;
if(ch[y][kind] == rt){
Rotate(rt,!kind);
Rotate(rt,kind);
}
else {
Rotate(y,kind);
Rotate(rt,kind);
}
}
}
pushup(rt);
if(goal == )
root = rt; }
int Get_max(int rt)
{
pushdown(rt);
while(ch[rt][]){
rt = ch[rt][];
pushdown(rt);
}
return rt;
}
void del(int root)
{
if(ch[root][] == ){
root = ch[root][];
pre[root] = ;
}
else {
int t = Get_max(ch[root][]);
splay(t,root);
ch[t][] = ch[root][];
pre[ch[root][]] = t;
root = t;
pre[root] = ;
pushup(root);
}
}
int main()
{
int i;
while(~scanf("%d",&n),n)
{
for(i=; i<=n; i++){
scanf("%d",&a[i].v);
a[i].id = i;
}
sort(a+,a+n+,cmp);
Init(); for(i=; i<=n; i++){
//cout<<"test1: "<<endl; splay(a[i].id,);
// debug();
lazy[ch[root][]] ^= ;
printf("%d",i+siz[ch[root][]]);
if(i < n)printf(" ");
else printf("\n");
del(root); }
}
}