-
Notifications
You must be signed in to change notification settings - Fork 941
Expand file tree
/
Copy pathLazySegmentTree.h
More file actions
69 lines (66 loc) · 1.99 KB
/
LazySegmentTree.h
File metadata and controls
69 lines (66 loc) · 1.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* Author: Simon Lindholm
* Date: 2016-10-08
* License: CC0
* Source: me
* Description: Segment tree with ability to add or set values of large intervals, and compute max of intervals.
* Can be changed to other things.
* Use with a bump allocator for better performance, and SmallPtr or implicit indices to save memory.
* Time: O(\log N).
* Usage: Node* tr = new Node(v, 0, sz(v));
* Status: stress-tested a bit
*/
#pragma once
#include "../various/BumpAllocator.h"
const int inf = 1e9;
struct Node {
typedef int T; // data type
struct L { int mset, madd; }; // lazy type
const T tneut = -inf; // neutral elements
const L lneut = {inf, 0};
T f (T a, T b) { return max(a, b); } // (any associative fn)
T apply (T a, L b) {
return b.mset != inf ? b.mset + b.madd : a + b.madd;
} // Apply lazy
L comb(L a, L b) {
if (b.mset != inf) return b;
return {a.mset, a.madd + b.madd};
} // Combine lazy
Node *l = 0, *r = 0;
int lo, hi; T val = tneut; L lazy = lneut;
Node(int lo,int hi):lo(lo),hi(hi){}//Large interval of tneut
Node(vector<T>& v, int lo, int hi) : lo(lo), hi(hi) {
if (lo + 1 < hi) {
int mid = lo + (hi - lo)/2;
l = new Node(v, lo, mid); r = new Node(v, mid, hi);
val = f(l->val, r->val);
}
else val = v[lo];
}
T query(int L, int R) {
if (R <= lo || hi <= L) return tneut;
if (L <= lo && hi <= R) return apply(val, lazy);
push();
return f(l->query(L, R), r->query(L, R));
}
void upd(int Le, int Ri, L x) {
if (Ri <= lo || hi <= Le) return;
if (Le <= lo && hi <= Ri) lazy = comb(lazy, x);
else {
push(), l->upd(Le, Ri, x), r->upd(Le, Ri, x);
val = f(l->query(lo, hi), r->query(lo, hi));
}
}
void set(int L, int R, int x) { upd(L, R, {x, 0}); }
void add(int L, int R, int x) { upd(L, R, {inf, x}); }
void push() {
if (!l) {
int mid = lo + (hi - lo)/2;
l = new Node(lo, mid), r = new Node(mid, hi);
}
l->lazy = comb(l->lazy, lazy);
r->lazy = comb(r->lazy, lazy);
lazy = lneut;
val = f(l->query(lo, hi), r->query(lo, hi));
}
};