洛谷 P4146 序列终结者
Description
Solution
fhq-treap
不得不说 \(fhq-treap\) 代码是真的短,真的好写。
挺板子的一道题。
-
区间加:打个 \(add\) 标记,不停下放即可,相应的 \(maxs\),\(val\),\(add\) 都要更新。
-
区间翻转:这就是个文艺平衡树板子,不多说了。(不会的话,可以看一下我的博客 洛谷 P3391 【模板】文艺平衡树)
-
查询区间最大值:把区间对应的子树找出来,输出这个子树记录的最大值即可。
注意 \(pushup\) 时要判断是否有左右子树,在向上传。
Code
#include <bits/stdc++.h>
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
using namespace std;
const int N = 5e4 + 10;
int n, m, root, tot;
struct Treap{
int ch[2], siz, maxs, val, wei, add, lazy;
}t[N];
int a, b, c;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
inline void pushup(int x){
t[x].siz = t[ls(x)].siz + t[rs(x)].siz + 1;
t[x].maxs = t[x].val;
if(ls(x)) t[x].maxs = max(t[x].maxs, t[ls(x)].maxs);
if(rs(x)) t[x].maxs = max(t[x].maxs, t[rs(x)].maxs);
}
inline void pushdown(int x){
if(!x) return;
if(t[x].lazy){
if(ls(x)) t[ls(x)].lazy ^= 1;
if(rs(x)) t[rs(x)].lazy ^= 1;
swap(ls(x), rs(x));
t[x].lazy = 0;
}
if(t[x].add){
if(ls(x)) t[ls(x)].val += t[x].add, t[ls(x)].add += t[x].add, t[ls(x)].maxs += t[x].add;
if(rs(x)) t[rs(x)].val += t[x].add, t[rs(x)].add += t[x].add, t[rs(x)].maxs += t[x].add;
t[x].add = 0;
}
}
inline void split(int x, int k, int &a, int &b){
if(!x){
a = b = 0;
return;
}
pushdown(x);
if(k >= t[ls(x)].siz + 1){
a = x;
split(rs(x), k - t[ls(x)].siz - 1, rs(x), b);
}else{
b = x;
split(ls(x), k, a, ls(x));
}
pushup(x);
}
inline int merge(int x, int y){
if(!x || !y) return x | y;
if(t[x].wei <= t[y].wei){
pushdown(x);
rs(x) = merge(rs(x), y);
pushup(x);
return x;
}else{
pushdown(y);
ls(y) = merge(x, ls(y));
pushup(y);
return y;
}
}
inline int newnode(int k){
t[++tot].val = t[tot].maxs = k, t[tot].siz = 1, t[tot].wei = rand();
return tot;
}
inline void insert(int k){
root = merge(root, newnode(k));
}
inline void Add(int l, int r, int k){
int len = r - l + 1;
split(root, l - 1, a, b);
split(b, len, b, c);
t[b].maxs += k;
t[b].val += k;
t[b].add += k;
root = merge(merge(a, b), c);
}
inline void Reverse(int l, int r){
split(root, l - 1, a, b);
split(b, r - l + 1, b, c);
t[b].lazy ^= 1;
root = merge(merge(a, b), c);
}
inline int Query(int l, int r){
split(root, l - 1, a, b);
split(b, r - l + 1, b, c);
int ans = t[b].maxs;
root = merge(merge(a, b), c);
return ans;
}
int main(){
n = read(), m = read();
for(int i = 1; i <= n; i++)
insert(0);
while(m--){
int op = read(), l = read(), r = read(), k;
if(op == 1) k = read(), Add(l, r, k);
else if(op == 2) Reverse(l, r);
else printf("%d\n", Query(l, r));
}
return 0;
}