序列终结者 Splay
1.注意在 split 和 merge时要特判一下边界, 否则就会出现边界错误的情况。
2.随时都要维护父指针。
3.在更新 maxv 和翻转标记时要判一下左右儿子是否都存在。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 100000 + 3; int f[maxn], ch[maxn][2], n,m,numv[maxn], maxv[maxn], siz[maxn], tag[maxn], root, cnt , lazy[maxn]; struct Operation { inline int get(int x){ return ch[f[x]][1] == x; } inline void pushdown(int x) { if(tag[x]) { swap(ch[ch[x][0]][0],ch[ch[x][0]][1]); swap(ch[ch[x][1]][0],ch[ch[x][1]][1]); if(ch[x][0]) tag[ch[x][0]] ^= 1; if(ch[x][1]) tag[ch[x][1]] ^= 1; tag[x] = 0; } if(lazy[x]) { if(ch[x][0]) maxv[ch[x][0]] += lazy[x], lazy[ch[x][0]] += lazy[x], numv[ch[x][0]] += lazy[x]; if(ch[x][1]) maxv[ch[x][1]] += lazy[x], lazy[ch[x][1]] += lazy[x], numv[ch[x][1]] += lazy[x]; lazy[x] = 0; } } inline void pushup(int x) { siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1; maxv[x] = numv[x]; if(ch[x][0]) maxv[x] = max(maxv[x], maxv[ch[x][0]]); if(ch[x][1]) maxv[x] = max(maxv[x], maxv[ch[x][1]]); } inline void rotate(int x) { int old = f[x], oldf = f[old], which = get(x); ch[old][which] = ch[x][which ^ 1], f[ch[old][which]] = old; ch[x][which ^ 1] = old, f[old] = x, f[x] = oldf; if(oldf) ch[oldf][ch[oldf][1] == old] = x; pushup(old); pushup(x); } inline void splay(int x,int &tar) { int a = f[tar]; for(int fa; (fa = f[x]) != a; rotate(x)) if(f[fa] != a) rotate(get(x) == get(fa) ? fa : x); tar = x; } inline int findx(int x, int top) { int cur = top; while(x > 0) { pushdown(cur); int ls = ch[cur][0], rs = ch[cur][1]; if(siz[ls] + 1 == x) return cur; if(siz[ls] >= x) cur = ls; else x -= siz[ls] + 1, cur = rs; } return 0; } inline void split(int &a,int nums,int &b) { if(nums == 0) { b = a, a = 0; return ; } if(nums == siz[a]) { b = 0; return ; } int u = findx(nums, a); splay(u, a); b = ch[a][1]; f[ch[a][1]] = 0, ch[a][1] = 0, pushup(a); } inline void merge(int &a,int b) { if(!a) { a = b; return ;} splay(findx(siz[a], a), a); ch[a][1] = b, f[b] = a; pushup(a); } void build(int l,int r,int &o,int fa) { if(l > r) return ; o = ++cnt; f[o] = fa, siz[o] = 1; int mid = (l + r) >> 1; build(l, mid - 1, ch[o][0], o); build(mid + 1, r, ch[o][1], o); pushup(o); } }T; int main() { //freopen("input.txt","r",stdin); scanf("%d%d",&n,&m); T.build(1, n, root, 0); while(m--) { int ops, l , r, v = 0; scanf("%d%d%d",&ops,&l,&r); int a = 0, b = 0; T.split(root, l - 1, a); T.split(a, r - l + 1, b); if(ops == 1) { scanf("%d",&v); maxv[a] += v, lazy[a] += v, numv[a] += v; T.pushup(a); } if(ops == 2) { swap(ch[a][0], ch[a][1]); tag[a] ^= 1; } if(ops == 3) { printf("%d\n",maxv[a]); } T.merge(root, a); T.merge(root, b); } return 0; }