1861: [Zjoi2006]Book 书架
2017-10-24 20:28
381 查看
1861: [Zjoi2006]Book 书架
Time Limit: 4 Sec Memory Limit:64 MB
Submit: 1822 Solved: 1038
[Submit][Status][Discuss]
Description
小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。 当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。
Input
第一行有两个数n,m,分别表示书的个数以及命令的条数;第二行为n个正整数:第i个数表示初始时从上至下第i个位置放置的书的编号;第三行到m+2行,每行一条命令。命令有5种形式: 1. Top S——表示把编号为S的书房在最上面。 2. Bottom S——表示把编号为S的书房在最下面。 3. Insert S T——T∈{-1,0,1},若编号为S的书上面有X本书,则这条命令表示把这本书放回去后它的上面有X+T本书; 4. Ask S——询问编号为S的书的上面目前有多少本书。 5. Query S——询问从上面数起的第S本书的编号。Output
对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。Sample Input
10 101 3 2 7 5 8 10 4 9 6
Query 3
Top 5
Ask 6
Bottom 3
Ask 3
Top 6
Insert 4 -1
Query 5
Query 2
Ask 2
Sample Output
29
9
7
5
3
HINT
数据范围100%的数据,n,m < = 80000
Source
Day2这一道题卡了五天!!!!!!
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 100000
struct Spaly
{
int ch[MAXN][2],f[MAXN],size[MAXN],cnt[MAXN],key[MAXN],rank[MAXN],val[MAXN];
int sz,root;
void init()
{
sz=root=0;
}
inline void clear(int x)
{
ch[x][0]=ch[x][1]=f[x]=size[x]=cnt[x]=key[x]=0;
}
inline bool get(int x)
{
return ch[f[x]][1]==x;
}
inline void update(int x)
{
if (x)
{
size[x]=cnt[x];
if (ch[x][0]) size[x]+=size[ch[x][0]];
if (ch[x][1]) size[x]+=size[ch[x][1]];
}
}
inline void rotate(int x)
{
int old=f[x],oldf=f[old],whichx=get(x);
ch[old][whichx]=ch[x][whichx^1];
f[ch[old][whichx]]=old;
ch[x][whichx^1]=old;
f[old]=x;
f[x]=oldf;
if (oldf)
ch[oldf][ch[oldf][1]==old]=x;
update(old);
update(x);
}
inline void splay(int x)
{
for (int fa; fa=f[x]; rotate(x))
if (f[fa])
rotate((get(x)==get(fa))?fa:x);
root=x;
}
inline void insert(int x)
{
if (root==0)
{
sz++;
ch[sz][0]=ch[sz][1]=f[sz]=0;
root=sz;
size[sz]=cnt[sz]=1;
key[sz]=x;
return;
}
int now=root,fa=0;
while(1)
{
if (x==key[now])
{
cnt[now]++;
update(now);
update(fa);
splay(now);
break;
}
fa=now;
now=ch[now][key[now]<x];
if (now==0)
{
sz++;
ch[sz][0]=ch[sz][1]=0;
f[sz]=fa;
size[sz]=cnt[sz]=1;
ch[fa][key[fa]<x]=sz;
key[sz]=x;
update(fa);
splay(sz);
break;
}
}
}
inline int find(int x)///x是第几名
{
int now=root,ans=0;
while(1)
{
if (x<key[now])
now=ch[now][0];
else
{
ans+=(ch[now][0]?size[ch[now][0]]:0);
if (x==key[now])
{
splay(now);
return ans+1;
}
ans+=cnt[now];
now=ch[now][1];
}
}
}
inline int findx(int x)///第x名是谁
{
int now=root;
while(1)
{
if (ch[now][0]&&x<=size[ch[now][0]])
now=ch[now][0];
else
{
int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
if (x<=temp) return key[now];
x-=temp;
now=ch[now][1];
}
}
}
inline int pre()
{
int now=ch[root][0];
while (ch[now][1]) now=ch[now][1];
return now;
}
inline int next()
{
int now=ch[root][1];
while (ch[now][0]) now=ch[now][0];
return now;
}
inline void del(int x)
{
int whatever=find(x);
if (cnt[root]>1)
{
cnt[root]--;
update(root);
return;
}
if (!ch[root][0]&&!ch[root][1])
{
clear(root);
root=0;
return;
}
if (!ch[root][0])
{
int oldroot=root;
root=ch[root][1];
f[root]=0;
clear(oldroot);
return;
}
else if (!ch[root][1])
{
int oldroot=root;
root=ch[root][0];
f[root]=0;
clear(oldroot);
return;
}
int leftbig=pre(),oldroot=root;
splay(leftbig);
ch[root][1]=ch[oldroot][1];
f[ch[oldroot][1]]=root;
clear(oldroot);
update(root);
}
} sp;
int main()
{
int n,m;
char op[50];
while(scanf("%d%d",&n,&m)!=EOF)
{
sp.init();
for(int i=1; i<=n; i++)
{
int tmp;
scanf("%d",&tmp);
sp.rank[tmp]=i;
sp.val[i]=tmp;
sp.insert(i);
}
while(m--)
{
int cho,ch;
scanf("%s %d",op,&ch);
switch(op[0])
{
case 'T':
{
sp.splay(ch=sp.rank[ch]);
int left=sp.ch[sp.root][0];
if(left==0)
break;
if(sp.ch[sp.root][1]==0)
{
sp.ch[sp.root][0]=0;
sp.ch[sp.root][1]=left;
break;
}
int pos=sp.next();
sp.ch[pos][0]=left;
sp.f[left]=pos;
sp.ch[sp.root][0]=0;
sp.splay(left);
}
break;
case 'B':
{
sp.splay(ch=sp.rank[ch]);
int right=sp.ch[sp.root][1];
if(right==0)
break;
if(sp.ch[sp.root][0]==0)
{
sp.ch[sp.root][1]=0;
sp.ch[sp.root][0]=right;
break;
}
int pos=sp.pre();
sp.ch[pos][1]=right;
sp.f[right]=pos;
sp.ch[sp.root][1]=0;
sp.splay(right);
}
break;
case 'A':
{
sp.splay(sp.rank[ch]);
printf("%d\n",sp.size[sp.ch[sp.root][0]]);
}
break;
case 'I':
{
scanf("%d",&cho);
if(cho==0)
break;
int s;
sp.splay(s=sp.rank[ch]);
int pre=sp.pre();
int net=sp.next();
if(cho==1)///右边
{
swap(sp.rank[ch],sp.rank[sp.val[net]]);
swap(sp.val[s],sp.val[net]);
}
else
{
swap(sp.rank[ch],sp.rank[sp.val[pre]]);
swap(sp.val[s],sp.val[pre]);
}
}
break;
case 'Q':
{
printf("%d\n",sp.val[sp.findx(ch)]);
}
break;
}
}
}
return 0;
}
相关文章推荐
- [BZOJ1861][Zjoi2006]Book 书架(平衡树)
- [bzoj1861][Zjoi2006]Book书架 splay
- BZOJ1861: [Zjoi2006]Book 书架
- BZOJ_1861_[Zjoi2006]Book 书架_splay
- [BZOJ1861] [Zjoi2006]Book 书架
- bzoj 1861: [Zjoi2006]Book 书架
- 1861: [Zjoi2006]Book 书架
- splay学习小结1.1【BZOJ 1861】[Zjoi2006]Book 书架
- 【BZOJ 1861】 [Zjoi2006]Book 书架
- BZOJ 1861: [Zjoi2006]Book 书架
- 1861: [Zjoi2006]Book 书架
- BZOJ1861: [Zjoi2006]Book 书架 Splay
- bzoj 1861 [Zjoi2006]Book 书架
- 【BZOJ1861】【Zjoi2006】Book 书架 Splay
- BZOJ 1861: [Zjoi2006]Book 书架
- BZOJ 1861 ZJOI2006 Book 书架 Splay
- BZOJ 1861 [Zjoi2006] Book 书架
- 【平衡树】【pb_ds】 bzoj1861 [Zjoi2006]Book 书架
- 【权值分块】bzoj1861 [Zjoi2006]Book 书架
- bzoj 1861 [Zjoi2006]Book 书架