【BZOJ1861】書架(ZJOI2006)-平衡樹復健題
阿新 • • 發佈:2019-01-27
測試地址:書架
做法:好久沒做平衡樹的題了,結果一道水題寫了一晚上……唉……
這一道題需要用到平衡樹。
這一題可以按書的編號建點,然後給每個點附上一個優先值,那麼按優先值從小到大排序就是當前書架上書的順序了。題目中的幾個操作就可以寫成這樣:
Top和Bottom操作:將一個點的優先值賦成比當前所有點優先值都小(或者都大),然後重新插入該點。
Insert操作:將相鄰兩個點的優先值交換,然後重新插入。
Ask和Query操作:經典的求某點排名或求某排名的點的操作。
以上這些操作就明顯可以用平衡樹維護了。
以下是本人程式碼:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100000
using namespace std;
int n,m,nowmn,nowmx,rt;
int val[N+10],siz[N+10],ch[N+10][2],fa[N+10];
char op[15];
void debug()
{
printf("===debug===\n");
for(int i=1;i<=n+2;i++)
printf("%d %d %d %d\n",ch[i][0 ],ch[i][1],fa[i],siz[i]);
}
void pushup(int v)
{
siz[v]=siz[ch[v][0]]+siz[ch[v][1]]+1;
}
void rotate(int x,bool f)
{
int y=fa[x];
ch[y][!f]=ch[x][f];
fa[ch[x][f]]=y;
ch[x][f]=y;
if (fa[y]) ch[fa[y]][ch[fa[y]][1]==y]=x;
fa[x]=fa[y];
fa[y]=x;
pushup(y);
}
void Splay(int x,int goal)
{
while(fa[x]!=goal)
{
if (fa[fa[x]]==goal) rotate(x,ch[fa[x]][0]==x);
else
{
int y=fa[x],z=fa[fa[x]];
bool f=(ch[y][1]==x);
if (ch[z][f]==y) rotate(y,!f),rotate(x,!f);
else rotate(x,!f),rotate(x,f);
}
}
pushup(x);
if (!goal) rt=x;
}
void insert(int &v,int now,int f)
{
if (!v)
{
v=now;
fa[v]=f;
siz[v]=1;
ch[v][0]=ch[v][1]=0;
Splay(v,0);
return;
}
siz[v]++;
insert(ch[v][val[now]>val[v]],now,v);
}
int rank(int v)
{
Splay(v,0);
return siz[ch[v][0]]+1;
}
int query(int x)
{
int v=rt;
while(siz[ch[v][0]]+1!=x)
{
if (siz[ch[v][0]]+1<x) x-=siz[ch[v][0]]+1,v=ch[v][1];
else v=ch[v][0];
}
return v;
}
void Delete(int v)
{
int r=rank(v);
Splay(query(r-1),0);
Splay(query(r+1),rt);
siz[rt]--,siz[ch[rt][1]]--;
ch[ch[rt][1]][0]=0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
val[x]=i;
}
rt=n+1;
nowmn=1,nowmx=n;
fa[n+1]=0,siz[n+1]=2,ch[n+1][0]=0,ch[n+1][1]=n+2,val[n+1]=-10000000;
fa[n+2]=n+1,siz[n+2]=1,ch[n+2][0]=ch[n+2][1]=0,val[n+2]=10000000;
siz[0]=0;
for(int i=1;i<=n;i++)
insert(rt,i,0);
for(int i=1;i<=m;i++)
{
int s,t;
scanf("%s",op);
scanf("%d",&s);
if (op[0]=='T')
{
Delete(s);
val[s]=--nowmn;
insert(rt,s,0);
}
if (op[0]=='B')
{
Delete(s);
val[s]=++nowmx;
insert(rt,s,0);
}
if (op[0]=='I')
{
scanf("%d",&t);
if (!t) {Splay(s,0);continue;}
int x=query(rank(s)+t);
Delete(s);
Delete(x);
swap(val[s],val[x]);
insert(rt,s,0);
insert(rt,x,0);
}
if (op[0]=='A')
{
printf("%d\n",rank(s)-2);
}
if (op[0]=='Q')
{
printf("%d\n",t=query(s+1));
Splay(t,0);
}
}
return 0;
}