原题传送门
序列终结者,用它来终结我这一阶段
S
p
l
a
y
Splay
Splay的练习再好不过了。。
三个操作,区间加,区间翻转,区间最值
最近以Splay为核心,看到翻转就想到用Splay,加和翻转用懒标记可以解决,同时可以维护一个最值,由pushup来更新size和mx(区间最值数组)
Code:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cctype>
#define maxn 100010
using namespace std;
int rt, sz, n, m, f[maxn], size[maxn], val[maxn], add[maxn], tag[maxn], mx[maxn], son[maxn][2];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void pushup(int x){
size[x] = size[son[x][0]] + size[son[x][1]] + 1;
mx[x] = max(val[x], max(mx[son[x][0]], mx[son[x][1]]));
}
int get(int x){ return son[f[x]][1] == x; }
void connect(int x, int y, int z){
f[x] = y, son[y][z] = x;
}
void rotate(int x){
int fa = f[x], ffa = f[fa], m = get(x), n = get(fa);
connect(son[x][m ^ 1], fa, m);
connect(fa, x, m ^ 1);
connect(x, ffa, n);
pushup(fa); pushup(x);
}
void splay(int x, int goal){
while (f[x] != goal){
int fa = f[x];
if (f[fa] != goal) rotate(get(x) == get(fa) ? fa : x);
rotate(x);
}
if (!goal) rt = x;
}
int build(int l, int r, int fa){
if (l > r) return 0;
int x = ++sz, mid = (l + r) >> 1;
f[x] = fa, size[x] = 1, val[x] = mx[x] = 0;
if (mid == 1 || mid == n + 2) val[x] = mx[x] = -2e9;
son[x][0] = build(l, mid - 1, x), son[x][1] = build(mid + 1, r, x);
pushup(x); return x;
}
void pushdown(int x){
if (add[x]){
if (son[x][0]) add[son[x][0]] += add[x], val[son[x][0]] += add[x], mx[son[x][0]] += add[x];
if (son[x][1]) add[son[x][1]] += add[x], val[son[x][1]] += add[x], mx[son[x][1]] += add[x];
}
if (tag[x]){
tag[son[x][0]] ^= 1; tag[son[x][1]] ^= 1; swap(son[x][0], son[x][1]);
}
add[x] = tag[x] = 0;
return;
}
int kth(int x){
int now = rt;
while (1){
pushdown(now);
if (size[son[now][0]] >= x) now = son[now][0]; else
if (size[son[now][0]] + 1 >= x) return now; else
x -= size[son[now][0]] + 1, now = son[now][1];
}
}
int main(){
n = read(), m = read();
mx[0] = -2e9;
rt = build(1, n + 2, 0);
while (m--){
int opt = read(), l = read(), r = read();
l = kth(l), r = kth(r + 2);
splay(l, 0); splay(r, l);
int u = son[son[rt][1]][0];
if (opt == 1){
int k = read();
add[u] += k, val[u] += k, mx[u] += k;
} else
if (opt == 2) tag[u] ^= 1; else printf("%d\n", mx[u]);
}
return 0;
}
当然也可以用fhq Treap
跟上面一样,不过方便非常多
简直无脑。。。
Code:
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
int rt, sz, val[maxn], size[maxn], key[maxn], son[maxn][2], add[maxn], mx[maxn], tag[maxn], n, m;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int addnode(){
++sz;
val[sz] = 0, key[sz] = rand() * rand(), size[sz] = 1;
return sz;
}
void pushup(int x){
size[x] = size[son[x][0]] + size[son[x][1]] + 1;
mx[x] = max(val[x], max(mx[son[x][0]], mx[son[x][1]]));
}
void pushdown(int x){
if (add[x]){
if (son[x][0]) add[son[x][0]] += add[x], val[son[x][0]] += add[x], mx[son[x][0]] += add[x];
if (son[x][1]) add[son[x][1]] += add[x], val[son[x][1]] += add[x], mx[son[x][1]] += add[x];
add[x] = 0;
}
if (tag[x]){
tag[son[x][0]] ^= 1, tag[son[x][1]] ^= 1;
swap(son[x][0], son[x][1]);
tag[x] = 0;
}
}
void split(int now, int w, int &u, int &v){
if (!now) u = v = 0; else{
pushdown(now);
if (size[son[now][0]] >= w) v = now, split(son[now][0], w, u, son[v][0]); else
u = now, split(son[now][1], w - size[son[now][0]] - 1, son[u][1], v);
pushup(now);
}
}
int merge(int u, int v){
if (!u || !v) return u + v;
if (key[u] >= key[v]){
pushdown(u);
son[u][1] = merge(son[u][1], v);
pushup(u);
return u;
} else{
pushdown(v);
son[v][0] = merge(u, son[v][0]);
pushup(v);
return v;
}
}
int main(){
srand(time(0));
n = read(), m = read();
mx[0] = -2e9;
for (int i = 1; i <= n; ++i) rt = merge(rt, addnode());
while (m--){
int opt = read(), l = read(), r = read(), x, y, z;
split(rt, r, x, y); split(x, l - 1, x, z);
if (opt == 1){
int k = read();
add[z] += k, val[z] += k, mx[z] += k;
} else
if (opt == 2) tag[z] ^= 1; else printf("%d\n", mx[z]);
rt = merge(merge(x, z), y);
}
return 0;
}