Splay 伸展树 bzoj3224 bzoj3223
Splay 伸展树, 平衡树的一种实现方法
splay的精髓在于 rotate函数, 这里不多作介绍, 以及有大牛把原理及实现方法解释的很清楚了,这里只贴一下自己实现的代码,代码参考 :史上最详尽的平衡树(splay)讲解与模板
下面是我自己的代码:
bzoj 3224
传送门:Tyvj 1728 普通平衡树
#include "iostream" #include "iomanip" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #pragma comment(linker, "/STACK:102400000,102400000") #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a,x) memset(a,x,sizeof(a)) #define step(x) fixed<< setprecision(x)<< #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) #define ll long long #define endl ("\n") #define ft first #define sd second #define lrt (rt<<1) #define rrt (rt<<1|1) using namespace std; const ll mod=1e9+7; const ll INF = 1e18+1LL; const int inf = 1e9+1e8; const double PI=acos(-1.0); const int N=1e6+100; int fa[N], ch[N][2], siz[N], cnt[N], key[N]; int sz, root; inline void update(int x){ siz[x] = cnt[x]; siz[x] += siz[ch[x][0]] + siz[ch[x][1]]; } inline void Clear(int x){ fa[x] = ch[x][0] = ch[x][1] = siz[x] = cnt[x] = key[x] = 0; } inline bool get(int x){ return ch[fa[x]][1] == x; } void Rotate(int x){ int old = fa[x], oldf = fa[old], which = get(x); ch[old][which] = ch[x][which^1], fa[ch[x][which^1]] = old; ch[x][which^1] = old, fa[old] = x; fa[x] = oldf; if(oldf) ch[oldf][ch[oldf][1]==old]=x; update(old), update(x); } void splay(int x){ while(fa[x]){ if(get(x) == get(fa[x]) && fa[fa[x]]) Rotate(fa[x]); Rotate(x);//cout<<" x \n"; } root = x; } void Insert(int x){ if(root == 0){ sz++, root = cnt[sz] = siz[sz] = 1, key[sz] = x; return; } int now = root, f = 0; while(1){ if(key[now] == x){ cnt[now]++, update(now), update(f), splay(now); break; } f = now, now = ch[now][x>key[now]]; if(now == 0){ sz++, cnt[sz] = 1, key[sz] = x, siz[sz] = 1, fa[sz] = f, ch[f][x>key[f]] = sz; update(f), splay(sz); break; } } } inline int finds(int v){ int now = root, ret=0; while(1){ if(v == key[now]){ ret += siz[ch[now][0]]; splay(now); return ret+1; } if(v < key[now]) now = ch[now][0]; else if(v > key[now]) ret += cnt[now] + siz[ch[now][0]], now = ch[now][1]; } } inline int findx(int x){ int now = root; while(1){ int t = siz[ch[now][0]] + cnt[now]; if(x <= siz[ch[now][0]]) now = ch[now][0]; else if(x <= t) return key[now]; else x -= t, now = ch[now][1]; } } inline int pre(){ int now = ch[root][0]; while(ch[now][1]) now = ch[now][1]; return now; } inline int nex(){ int now = ch[root][1];//cout<<key[ch[now][1]]<<" u \n"; while(ch[now][0]) now = ch[now][0]; return now; } inline void del(int x){//cout<<key[root]<<endl; finds(x); if(cnt[root]>1){ cnt[root]--, update(root); return; } if(ch[root][0]==0 && ch[root][1]==0){ Clear(root), root =0; return; } if(ch[root][0] && ch[root][1]){ int p = pre(), old = root; splay(p); fa[ch[old][1]] = root; ch[root][1] = ch[old][1]; Clear(old), update(root); return; } int old = root; root = ch[root][ch[root][0]==0], fa[root] = 0, Clear(old); } int main(){ int n, opt, x; scanf("%d", &n); for (int i=1; i<=n; ++i){ scanf("%d %d",&opt, &x); switch(opt){ case 1: Insert(x); break; case 2: del(x); break; case 3: printf("%d\n",finds(x)); break; case 4: printf("%d\n",findx(x)); break; case 5: Insert(x); printf("%d\n", key[pre()]); del(x); break; case 6: Insert(x); printf("%d\n", key[nex()]); del(x); break; } } return 0; }
bzoj 3223
传送门:HYSBZ - 3223
#include "iostream" #include "iomanip" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #pragma comment(linker, "/STACK:102400000,102400000") #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a,x) memset(a,x,sizeof(a)) #define step(x) fixed<< setprecision(x)<< #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) #define ll long long #define endl ("\n") #define ft first #define sd second #define lrt (rt<<1) #define rrt (rt<<1|1) using namespace std; const ll mod=1e9+7; const ll INF = 1e18+1LL; const int inf = 1e9+1e8; const double PI=acos(-1.0); const int N=1e5+100; int siz[N], ch[N][2], cnt[N], key[N], fa[N], lazy[N]; int root, sz, n, m; void Clear(int x){ siz[x] = ch[x][0] = ch[x][1] = cnt[x] = key[x] = fa[x] = 0; } void update(int x){ siz[x] = cnt[x]; siz[x] += siz[ch[x][0]] + siz[ch[x][1]]; } bool get(int x){ return ch[fa[x]][1] == x; } void pushdown(int x){ if(lazy[x]){ swap(ch[x][0], ch[x][1]); lazy[ch[x][0]] ^= 1, lazy[ch[x][1]] ^= 1; } lazy[x] = 0; } void Rotate(int x){ pushdown(fa[x]), pushdown(x); int fx = fa[x], ffx = fa[fx], which = get(x); ch[fx][which] = ch[x][which^1], fa[ch[x][which^1]] = fx; ch[x][which^1] = fx, fa[fx] = x; fa[x] = ffx; if(ffx) ch[ffx][ch[ffx][1]==fx] = x; update(fx), update(x); } void splay(int x, int goal){ while(fa[x] != goal){ if(get(x)==get(fa[x]) && fa[fa[x]] && fa[fa[x]]!=goal) Rotate(fa[x]); Rotate(x); } if(goal==0) root = x; } int findx(int x){ int now = root; pushdown(now); while(1){ int t = cnt[now] + siz[ch[now][0]]; if(x <= siz[ch[now][0]]) now = ch[now][0]; else if(x <= t) return now; else x -= t, now = ch[now][1]; pushdown(now); } } void change(int l, int r){ int fl = findx(l), fr = findx(r+2); //cout<<key[fl]<<"qq\n"; splay(fl, 0), splay(fr, root); lazy[ch[ch[root][1]][0]] ^= 1; } void Insert(int x){ if(root == 0){ sz++, root = cnt[sz] = siz[sz] = 1, key[sz] = x; return; } int now = root, f = 0; while(1){ if(key[now] == x){ cnt[now]++, update(now), update(f), splay(now, 0); break; } f = now, now = ch[now][x>key[now]]; if(now == 0){ sz++, cnt[sz] = 1, key[sz] = x, siz[sz] = 1, fa[sz] = f, ch[f][x>key[f]] = sz; update(f), splay(sz, 0); break; } } } int build(int l, int r, int f){//cout<<" UU\n"; if(l > r) return 0; int mid = l+r>>1, u = ++sz; if(l == r){ cnt[u] = 1, siz[u] = 1, fa[u] = f, key[u] = l-1; return u; } ch[u][0] = build(l, mid-1, u); ch[u][1] = build(mid+1, r, u); cnt[u] = 1, siz[u] = 1, fa[u] = f, key[u] = mid-1; update(u); return u; } void dfs(int x){ if(!x) return; pushdown(x); dfs(ch[x][0]); if(key[x]>=1 && key[x]<=n) printf("%d ", key[x]); dfs(ch[x][1]); } int main(){ scanf("%d %d", &n, &m); //for(int i=0; i<=n+1; ++i) Insert(i); root = build(1, n+2, 0); while(m--){ int l, r; scanf("%d %d", &l, &r); change(l, r); } dfs(root); return 0; }