1.维护BST
例:BZOJ 1588
splay 通过旋转保证时间复杂度
定义 u.lson.x < u.x < u.rson.x (BST定义)
旋转与splay(将点v旋转至根)
inline void lnk(int u,int f,int k) {T[u].fa = f; T[f].son[k] = u;}
inline void rot(int v) {
int u = T[v].fa, k = (T[u].son[0] == v) ? 0 : 1;
lnk(v,T[u].fa,(T[T[u].fa].son[0] == u) ? 0 : 1);
lnk(T[v].son[!k],u,k); lnk(u,v,!k);
}
inline void splay(int v) {
for (int u;u=T[v].fa;rot(v)) if (T[u].fa) rot(((T[T[v].fa].son[0] == v) ^ (T[T[u].fa].son[0] == u)) ? v : u);
}
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100100
using namespace std;
struct node {int son[2],fa,x;} T[N];
inline void lnk(int u,int f,int k) {T[u].fa = f; T[f].son[k] = u;}
inline void rot(int v) {
int u = T[v].fa, k = (T[u].son[0] == v) ? 0 : 1;
lnk(v,T[u].fa,(T[T[u].fa].son[0] == u) ? 0 : 1);
lnk(T[v].son[!k],u,k); lnk(u,v,!k);
}
void splay(int v) {
for (int u;u=T[v].fa;rot(v)) if (T[u].fa) rot(((T[T[v].fa].son[0] == v) ^ (T[T[u].fa].son[0] == u)) ? v : u);
}
int n,now = 1,i,x,p,q,ans,root;
inline bool set(int u,int x) {
while (T[u].x != x && T[u].son[T[u].x < x]) u = T[u].son[T[u].x < x];
if (T[u].x == x) {splay(root = u); return true;}
else {
T[T[u].son[T[u].x < x] = ++now] = (node) {0,0,u,x};
splay(root = now); return false;
}
}
int pre(int u) {if (!u) return 0xbfffffff; while (T[u].son[1]) u = T[u].son[1]; return T[u].x;}
int suc(int u) {if (!u) return 0x3fffffff; while (T[u].son[0]) u = T[u].son[0]; return T[u].x;}
int main() { freopen("_in.txt","r",stdin);
scanf("%d%d",&n,&x); ans = T[root = now = 1].x = x;
while (--n) {
scanf("%d",&x);
if (set(root,x)) continue;
ans += min(x-pre(T[root].son[0]),suc(T[root].son[1])-x);
} printf("%d",ans);
}
2.线段树+
例题:luogu3391
无论 splay 怎么旋转,中序遍历不变
理论上 splay 可以实现线段树的所有操作 (包括lazy_tag)
因此可用 splay 处理区间反转问题
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100100
using namespace std;
struct node {int son[2],fa,x,sum,lazy;} T[N];
int root,now,n,m,i;
inline void lnk(int u,int f,int k) {T[u].fa = f; T[f].son[k] = u;}
inline void rot(int v) {
int u = T[v].fa, k = T[u].son[1] == v;
lnk(v,T[u].fa,T[T[u].fa].son[1] == u);
lnk(T[v].son[!k],u,k); lnk(u,v,!k);
T[u].sum = T[T[u].son[0]].sum + T[T[u].son[1]].sum + 1;
T[v].sum = T[T[v].son[0]].sum + T[T[v].son[1]].sum + 1;
}
inline void splay(int v,int to) {
for (int u;(u=T[v].fa) != to && u;rot(v)) if (T[u].fa != to && u) rot(((T[T[u].fa].son[1] == u) ^ (T[T[u].fa].son[1] == u)) ? v : u);
if (!to) root = v;
}
inline void push_down(int u) {
if (T[u].lazy) T[T[u].son[0]].lazy ^= 1, T[T[u].son[1]].lazy ^= 1, swap(T[u].son[0],T[u].son[1]), T[u].lazy = 0;
}
int build(int l=0,int r=n+1) {
if (l > r) return 0;
int mid = (l+r) >> 1, ls = build(l,mid-1), u = ++now, rs = build(mid+1,r);
T[ls].fa = T[rs].fa = u;
T[u].sum = T[T[u].son[0] = ls].sum + T[T[u].son[1] = rs].sum + 1; T[u].x = mid;
return u;
}
int kth(int u,int k) {
push_down(u);
if (k == T[T[u].son[0]].sum + 1) return u;
if (k <= T[T[u].son[0]].sum) return kth(T[u].son[0],k); else return kth(T[u].son[1],k - T[T[u].son[0]].sum - 1);
}
void dfs(int u) {
if (!u) return; push_down(u);
dfs(T[u].son[0]);
if (T[u].x != 0 && T[u].x != n+1) printf("%d ",T[u].x);
dfs(T[u].son[1]);
}
int main() {
scanf("%d%d",&n,&m);
root = build(0,n+1);
for (int ql,qr;m--;) {
scanf("%d%d",&ql,&qr);
ql = kth(root,ql); qr = kth(root,qr+2);
splay(ql,0); splay(qr,ql);
T[T[qr].son[0]].lazy ^= 1;
}
dfs(root); putchar(10);
}