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 }
弱者究竟为何而战?!