1. 程式人生 > >「BZOJ 1251」序列終結者「Splay」

「BZOJ 1251」序列終結者「Splay」

像線段樹那樣,維護一個懶標記就行

#include <algorithm>
#include <cstdio>
using namespace std;

namespace Splay {
	const int N = 1e5 + 10;
	int root, ch[N][2], sz[N], fa[N];
	int tag[N], mx[N], va[N];
	bool rev[N];
	inline int dir(int x) {
		return ch[fa[x]][1] == x;
	}
	inline void upd(int x) {
		sz[x] = 1
+ sz[ch[x][0]] + sz[ch[x][1]]; mx[x] = max(va[x], max(mx[ch[x][0]], mx[ch[x][1]])); } inline void rotate(int x) { int d = dir(x), f = fa[x]; if(fa[x] = fa[f]) ch[fa[x]][dir(f)] = x; if(ch[f][d] = ch[x][d ^ 1]) fa[ch[f][d]] = f; fa[ch[x][d ^ 1] = f] = x; upd(f), upd(x); } inline void pushd
(int x) { if(tag[x]) { if(ch[x][0]) { tag[ch[x][0]] += tag[x]; va[ch[x][0]] += tag[x]; mx[ch[x][0]] += tag[x]; } if(ch[x][1]) { tag[ch[x][1]] += tag[x]; va[ch[x][1]] += tag[x]; mx[ch[x][1]] += tag[x]; } tag[x] = 0; } if(rev[x]) { rev[x] = 0; rev[ch[x][0]] ^
= 1; rev[ch[x][1]] ^= 1; swap(ch[x][0], ch[x][1]); } } int build(int l, int r) { if(l > r) return 0; int m = l + r >> 1; sz[m] = 1; if(l == r) return l; int L = build(l, m - 1), R = build(m + 1, r); if(ch[m][0] = L) fa[L] = m; if(ch[m][1] = R) fa[R] = m; sz[m] += sz[L] + sz[R]; return m; } int top, st[N]; void splay(int u, int tof = 0) { top = 0; for(int x = u; fa[x]; x = fa[x]) st[top ++] = fa[x]; while(top --) pushd(st[top]); pushd(u); for(int x = u; fa[x] != tof; rotate(x)) if(fa[fa[x]] != tof) rotate(dir(x) == dir(fa[x]) ? fa[x] : x); if(!tof) root = u; } int kth(int u, int k) { int v = u; while(1) { pushd(v); if(k <= sz[ch[v][0]]) v = ch[v][0]; else { k -= sz[ch[v][0]] + 1; if(k == 0) break ; v = ch[v][1]; } } splay(v, fa[u]); return v; } void reverse(int l, int r) { int u = kth(root, r + 1); int v = kth(ch[u][0], l - 1); rev[ch[v][1]] ^= 1; } void addv(int l, int r, int val) { int u = kth(root, r + 1); int v = kth(ch[u][0], l - 1); tag[ch[v][1]] += val; mx[ch[v][1]] += val; va[ch[v][1]] += val; } int qmax(int l, int r) { int u = kth(root, r + 1); int v = kth(ch[u][0], l - 1); return mx[ch[v][1]]; } } int main() { int n, m; scanf("%d%d", &n, &m); Splay :: mx[0] = - 1 << 30; Splay :: root = Splay :: build(1, n + 2); for(int i = 1, op, l, r, v; i <= m; i ++) { scanf("%d%d%d", &op, &l, &r); ++ l; ++ r; if(op == 1) { scanf("%d", &v); Splay :: addv(l, r, v); } if(op == 2) Splay :: reverse(l, r); if(op == 3) printf("%d\n", Splay :: qmax(l, r)); } return 0; }