「BZOJ 1251」序列終結者「Splay」
阿新 • • 發佈:2018-12-18
像線段樹那樣,維護一個懶標記就行
#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;
}