[ZJOI2006]书架 Treap

来源:互联网 发布:sql的distinct怎么删除 编辑:程序博客网 时间:2024/05/23 22:15

题目描述

小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。

小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。

当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。

久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。

输入输出格式

输入格式:
第一行有两个数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本书的编号。

输出格式:
对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。

输入输出样例

输入样例#1:
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
输出样例#1:
2
9
9
7
5
3
说明

100%的数据,n,m <= 80000

调试一万年系列又一题
这题主要是要给每本书另外定一个优先级作为v,用数组a来记下它们的优先级,再在树里面另开一个值记编号就好了,记住,它们的优先级并不等于它们现在所在的位置
所以插入的应该是a[x]而不是x
top操作就是把这本书的优先级变为最小再插入回去,bottom操作就是把这本书的优先级变为最大再插入回去,insert就是把两本书的优先级交换再插回去
query x 对应 kth(x),ask x 对应 find(a[x])
以上

下面是代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define ll intusing namespace std;const int N=80010;ll n,a[N],now,m,maxn,minn;struct node{    node* ch[2];ll s,r,v,w;    node(int v):v(v){ch[0]=ch[1]=NULL;s=1;r=rand();w=now;}    void maintain()     {         s=1;         if(ch[0] != NULL) s+=ch[0]->s;         if(ch[1] != NULL) s+=ch[1]->s;     }    int cmp(int x){if(v == x) return -1;return v < x;}};node* rt;void rotate(node* &o,int d){    node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;    o->maintain();k->maintain();o=k;}void ins(node* &o,int x){    if(o == NULL) {o=new node(x);return ;}    int d=(o->v < x);ins(o->ch[d],x);    if(o->ch[d]->r > o->r) rotate(o,d^1);    o->maintain();}void del(node* &o,int x){    if(o == NULL) return ;    int d=o->cmp(x);    if(d == -1)    {        if(o->ch[0] != NULL && o->ch[1] != NULL)        {            int d2=(o->ch[0]->r > o->ch[1]->r);            rotate(o,d2);del(o->ch[d2],x);        }        else {if(o->ch[0] == NULL) o=o->ch[1];else o=o->ch[0];}    }    else del(o->ch[d],x);    if(o != NULL) o->maintain();}void kth(node* &o,int k,int &ans){    if(o == NULL || k <=0 || k > o->s) return ;    int ss=(o->ch[0] == NULL ? 0 : o->ch[0]->s);    if(k == ss+1) {ans=o->w;return ;}    if(k <= ss) kth(o->ch[0],k,ans);    else kth(o->ch[1],k-ss-1,ans);}int rank(node* &o,int x){    if(o == NULL) return 0;    int d=o->cmp(x),ss=(o->ch[0] == NULL ? 0 : o->ch[0]->s);    if(d == -1) return ss+1;    if(d == 0) return rank(o->ch[0],x);    return rank(o->ch[1],x)+ss+1;}int read(){    int out=0,f=1;char c=getchar();     while(c < '0' || c > '9')      {if(c == '-') f=-1;c=getchar();}    while(c >= '0' && c <= '9' )     {out=(out<<1)+(out<<3)+c-'0';c=getchar();}     return out*f;}void solve(){    n=read(),m=read(),maxn=n,minn=1;    for(int i=1;i<=n;i++)    {        now=read();        ins(rt,i);        a[now]=i;    }    for(int i=1;i<=m;i++)    {        string cmd;        cin>>cmd;        if(cmd == "Query")        {            int k=read(),ans;kth(rt,k,ans);            printf("%d\n",ans);        }        if(cmd == "Ask")        {            int x=read();            printf("%d\n",rank(rt,a[x])-1);        }        if(cmd == "Top")        {            int x=read();            del(rt,a[x]);            a[x]=--minn;            now=x;ins(rt,a[x]);        }        if(cmd == "Bottom")        {            int x=read();            del(rt,a[x]);            a[x]=++maxn;            now=x;ins(rt,a[x]);        }        if(cmd == "Insert")        {            int x=read(),t=read();            if(t)            {                int rank1=rank(rt,a[x]),rank2=rank1+t;                int x2;kth(rt,rank2,x2);                del(rt,a[x]);del(rt,a[x2]);                a[x]+=a[x2];a[x2]=a[x]-a[x2];a[x]-=a[x2];                now=x;ins(rt,a[x]);now=x2;ins(rt,a[x2]);            }        }    }}int main(){    solve();    return 0;}
原创粉丝点击