[ZJOI2006]书架
Posted shatianming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ZJOI2006]书架相关的知识,希望对你有一定的参考价值。
#include<bits/stdc++.h> #define MAXN 400005 using namespace std; int n,q,a,b; string tp; int date[MAXN],bianhao[MAXN]; struct Splay{ int num[MAXN],ch[MAXN][2],sz[MAXN],f[MAXN],cnt[MAXN],rt,tot,tag[MAXN]; int get(int x){ return (x==ch[f[x]][1]); } int up(int x){ sz[x] = cnt[x]; if(ch[x][0])sz[x] = sz[x]+sz[ch[x][0]]; if(ch[x][1])sz[x] = sz[x]+sz[ch[x][1]]; return 0; } int rote(int x){ int y = f[x],z = f[y],k = get(x),p = get(y); if(y==0)return 0; if(z)ch[z][p] = x; if(ch[x][k^1])f[ch[x][k^1]] = y; ch[y][k] = ch[x][k^1]; ch[x][k^1] = y; f[x] = z; f[y] = x; up(y);up(x); return 0; } int splay(int x){ for(int y = f[x];(y = f[x]);rote(x)){ rote((get(x)==get(y))?y:x); } rt = x; return 0; } int rank(int x){ int now=rt,ans=1; while(1){ if(num[now]<=x){ ans = ans+sz[ch[now][0]]; if(num[now]==x){ splay(now); return ans; } ans = ans+cnt[now]; now = ch[now][1]; } else{ now = ch[now][0]; } } } int pre(){//前继 比她小的最大 int now = ch[rt][0]; while(ch[now][1])now = ch[now][1]; return now; } int suc(){ int now = ch[rt][1]; while(ch[now][0])now = ch[now][0]; return now; } int add(int x){ int now = rt; while(1){ if(num[now]==x){ cnt[now]++; splay(now); return 0; } int to = (num[now]<x); if(!ch[now][to]){ tot++; ch[now][to] = tot; num[tot] = x; f[tot] = now; cnt[tot] = 1; sz[tot] = 1; splay(tot); return 0; } else now = ch[now][to]; } } int kth(int x){ int now =rt; while(1){ if(sz[ch[now][0]]<x&&ch[now][0]){ x = x-sz[ch[now][0]]; if(x<=cnt[now])return now; x = x-cnt[now]; now = ch[now][1]; } else if(!ch[now][0]){ if(x<=cnt[now])return now; x = x-cnt[now]; now = ch[now][1]; } else{ now = ch[now][0]; } } } int del(int x){ splay(x); int fu = pre(),ck = suc(); if(fu==0){ int hj = ch[rt][1]; ch[rt][0] = ch[rt][1] = f[rt] = 0; rt = hj; return 0; } if(ck==0){ int hj = ch[rt][0]; ch[rt][0] = ch[rt][1] = f[rt] = 0; rt = hj; return 0; } splay(fu); splay2(ck); ch[ch[ck][0]][0] = ch[ch[ck][0]][1] = f[ch[ck][0]] = 0; ch[ck][0] = 0; up(ch[ck][1]); up(fu); } int chajinqu(int x,int y){ if(y==0)return 0; splay(x); int fu = pre(),ck = suc(); if(y==1&&ck!=0){ swap(bianhao[date[rt]],bianhao[date[ck]]); swap(date[rt],date[ck]); swap(num[rt],num[ck]); } else if(fu!=0){ swap(bianhao[date[rt]],bianhao[date[fu]]); swap(date[rt],date[fu]); swap(num[rt],num[fu]); } } int splay2(int x){ for(int y = f[x];(y = f[x])!=rt;rote(x)){ if(f[y]!=rt)rote((get(x)==get(y))?y:x); } return 0; } int minl(){ int now = rt; while(ch[now][0])now = ch[now][0]; return now; } int maxl(){ int now = rt; while(ch[now][1])now = ch[now][1]; return now; } }T; int main(){ cin>>n>>q; for(int i=1;i<=n;i++){ cin>>date[i]; bianhao[date[i]] = i; T.add(i); } //知道了每个树节点所对于的书本编号.... for(int i=1;i<=q;i++){ cin>>tp; if(tp=="Top"){ cin>>a;//把ma所对应的树的节点删掉,然后在树的最左插入... T.del(bianhao[a]); if(T.minl()==0){ T.ch[T.rt][0] = bianhao[a]; T.f[bianhao[a]] = T.rt; T.up(bianhao[a]);T.up(T.rt); } else{ T.splay(T.minl()); T.ch[T.rt][0] = bianhao[a]; T.f[bianhao[a]] = T.rt; T.up(bianhao[a]);T.up(T.rt); } } else if(tp=="Bottom"){ cin>>a;//把ma所对应的树的节点删掉,然后在树的最右插入... T.del(bianhao[a]); if(T.maxl()==0){ T.ch[T.rt][1] = bianhao[a]; T.f[bianhao[a]] = T.rt; T.up(bianhao[a]);T.up(T.rt); } else{ T.splay(T.maxl()); T.ch[T.rt][1] = bianhao[a]; T.f[bianhao[a]] = T.rt; T.up(bianhao[a]);T.up(T.rt); } } else if(tp=="Insert"){ //这里炸了 cin>>a>>b; T.chajinqu(bianhao[a],b); } else if(tp=="Ask"){ cin>>a; T.splay(bianhao[a]); printf("%d ",T.sz[T.ch[T.rt][0]]); } else if(tp=="Query"){ cin>>a; printf("%d ",date[T.kth(a)]); } } }
有空来调,好毒....
以上是关于[ZJOI2006]书架的主要内容,如果未能解决你的问题,请参考以下文章