您的位置:首页 > 其它

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 10

1 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

2

9

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: