BZOJ1861 [Zjoi2006]Book 书架

从6点调到了现在22:19:07。。脑子晕倒死。

用splay做,一开始怎么想也不知道该怎么play。

想了个办法,用pos[i]表示编号为i的书在树上的节点编号

s[i]表示树上的节点i代表的是哪本书。

val[i]表示节点i的权值,这里的权值按照书从上到下的大小顺序来赋值,用来建树

TOP:先把树里面代表书S的那个节点删掉,然后再重新建一个节点把S放进去,这时候,

    为了使新的节点在最前方,开一个mmin表示已经出现过的最小的数,

    每次要把节点加入进去的时候插入几点的权值就是 --mmin;

BOT:同上;

INSERT:找到S的前驱或后继,然后调换一下顺序就ok

ASK:查询排名

QUERY:查询排名为K的书的编号。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 const int maxn = 200005;
  6 int fa[maxn],son[2][maxn],val[maxn],pos[maxn],siz[maxn],s[maxn];
  7 int root,tot,mmax,mmin;
  8 void rota(int w,int x){
  9     int y = fa[x];
 10     son[!w][y] = son[w][x];
 11     if(son[w][x])fa[son[w][x]] = y;
 12     fa[x] = fa[y];
 13     if(fa[y])son[y==son[1][fa[y]]][fa[y]] = x;
 14     fa[y] = x;
 15     son[w][x] = y;
 16     siz[y] = siz[y]-siz[x]+siz[son[!w][y]];
 17     siz[x] = siz[x]-siz[son[!w][y]]+siz[y];
 18 }
 19 void splay(int x,int y){
 20     while(fa[x]!=y){
 21         if(fa[fa[x]]==y)rota(x==son[0][fa[x]],x);
 22         else {
 23             int w = fa[x]==son[0][fa[fa[x]]];
 24             if(x==son[w][fa[x]]){
 25                 rota(!w,x);rota(w,x);
 26             }
 27             else {
 28                 rota(w,fa[x]);rota(w,x);
 29             }
 30         }
 31     }
 32     if(y==0)root = x;
 33 }
 34 void Ins(int v){
 35     int x = root;
 36     while(1){
 37         siz[x]++;
 38         if(v<val[x]){
 39             if(son[0][x])x = son[0][x];
 40             else break;
 41         }
 42         else {
 43             if(son[1][x])x = son[1][x];
 44             else break;
 45         }
 46     }
 47     fa[++tot] = x;
 48     val[tot] = v;
 49     siz[tot] = 1;
 50     if(v<val[x])son[0][x] = tot;
 51     else son[1][x] = tot;
 52     splay(tot,0);
 53 }
 54 int getPre(int x){
 55     splay(x,0);x = son[0][x];///先把x从根节点拿到子树上
 56     if(!x)return 0;
 57     while(son[1][x])x = son[1][x];
 58     return x;
 59 }
 60 int getNext(int x){
 61     splay(x,0);x = son[1][x];
 62     if(!x)return 0;
 63     while(son[0][x])x = son[0][x];
 64     return x;
 65 }
 66 void Del(int x){
 67     splay(x,0);
 68     int y = getPre(x),z = getNext(x);
 69     if(y==0&&z==0){root = 0;return;}
 70     if(y)splay(y,0);
 71     if(z)splay(z,y);
 72     if(y==0){son[0][z] = 0,siz[z]--;return;}
 73     if(z==0){son[1][y] = 0,siz[y]--;return;}
 74     son[0][z] = 0;
 75     siz[z]--,siz[y]--;
 76 }
 77 int getRank(int x){
 78     splay(x,0);
 79     return siz[son[0][x]];
 80 }
 81 int getK(int k){
 82     int x = root;
 83     while(k!=siz[son[0][x]]+1){
 84         if(k<=siz[son[0][x]])x = son[0][x];
 85         else {
 86             k-=(siz[son[0][x]]+1);///以后千万记得先更新k之后再更新x!!!!
 87             x = son[1][x];
 88         }
 89     }
 90     return s[x];
 91 }
 92 int main()
 93 {
 94     int n,m;scanf("%d%d",&n,&m);
 95     for(int i = 1;i<=n;++i){
 96         int t;scanf("%d",&t);
 97         if(i==1){
 98             root = ++tot;
 99             val[1] = 1;
100             siz[1] = 1;
101             s[1] = t;
102         }
103         else Ins(i);
104         pos[t] = tot;
105         s[tot] = t;
106     }
107     mmin = 1;mmax = n;
108     while(m--){
109         char ss[10];
110         int a,b,x;
111         scanf("%s%d",ss,&a);
112         if(ss[0]==‘T‘){
113             Del(pos[a]);
114             Ins(--mmin);pos[a] = tot;
115             s[tot] = a;
116         }
117         else if(ss[0]==‘B‘){
118             Del(pos[a]);Ins(++mmax);
119             pos[a] = tot;
120             s[tot] = a;
121         }
122         else if(ss[0]==‘I‘){
123             scanf("%d",&b);
124             if(!b)continue;
125             if(b==-1)x = getPre(pos[a]);
126             else x = getNext(pos[a]);
127             x = s[x];
128             swap(pos[a],pos[x]);
129             swap(s[pos[a]],s[pos[x]]);
130         }
131         else if(ss[0]==‘A‘)printf("%d\n",getRank(pos[a]));
132         else printf("%d\n",getK(a));
133     }
134     return 0;
135 }
时间: 2024-10-12 11:21:12

BZOJ1861 [Zjoi2006]Book 书架的相关文章

【权值分块】bzoj1861 [Zjoi2006]Book 书架

权值分块……rank3……没什么好说的. 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 int n,sz,sum,x,y,l[501],r[501],Min,Max,sumv[501],num[250001],m,v[250001],p[250001]; 6 bool b[250001]; 7 char op[6],c; 8 int Num,CH[1

【平衡树】【pb_ds】 bzoj1861 [Zjoi2006]Book 书架

需要用数组记录编号为i的书的位置,和位置i处的书的编号. Code: 1 #include<cstdio> 2 #include<ext/pb_ds/assoc_container.hpp> 3 #include<ext/pb_ds/tree_policy.hpp> 4 using namespace std; 5 using namespace __gnu_cxx; 6 using namespace __gnu_pbds; 7 tree<int,null_ty

bzoj1861 [Zjoi2006]Book 书架——splay

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1861 发现自己想splay的时候总是纠结那个点权是什么,因为splay原本是二分查找树... 但其实splay已经不是维护点权大小顺序的,它的最大作用就在于无论怎样旋转都保持着中序遍历这个相对位置不变: 所以很对应这道题,用splay进行各种操作的同时书的摆放顺序是不变的: 假设出一个'1'点.一个'n+1'点方便操作,所以整体+1: 这个建树的方法不错呢. 代码如下: #include<

bzoj1861: [Zjoi2006]Book 书架(平衡树)

原题链接 题目描述:小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置.不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1.X或X+1本书. 当然也有特殊情况,比如在看书的时候突然电话响了或

BZOJ 1861: [Zjoi2006]Book 书架 (splay)

1861: [Zjoi2006]Book 书架 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1453  Solved: 822[Submit][Status][Discuss] Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位

BZOJ 1861: [Zjoi2006]Book 书架 splay

1861: [Zjoi2006]Book 书架 Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置.不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1.X或X+1本

[Zjoi2006]Book 书架

pre.cjk { font-family: "Droid Sans Fallback", monospace } p { margin-bottom: 0.25cm; line-height: 120% } a:link { } 1861: [Zjoi2006]Book 书架 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1581  Solved: 884[Submit][Status][Discuss] Description 小T有一

BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

[题目分析] 模板题目. 首尾两个虚拟结点,十分方便操作. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #include

[题解]bzoj 1861 Book 书架 - Splay

1861: [Zjoi2006]Book 书架 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1396  Solved: 803[Submit][Status][Discuss] Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位