1 module dkh.segtree.simpleseg; 2 3 import dkh.segtree.primitive; 4 5 import std.functional : binaryFun; 6 7 /** 8 SegTree 9 10 T型の配列aについて、opTT(a[l..r])が高速に計算できる。 11 opTTは結合率を満たす2引数関数, eTは単位元。 12 */ 13 alias SimpleSeg(T, alias opTT, T eT, alias Engine = SimpleSegEngine) = 14 SegTree!(Engine, T, binaryFun!opTT, eT); 15 16 /// 17 unittest { 18 import std.algorithm : max; 19 ///int型でmax(...)が計算できる、つまりRMQ 20 auto seg = SimpleSeg!(int, (a, b) => max(a, b), 0)(3); 21 22 //[2, 1, 4] 23 seg[0] = 2; seg[1] = 1; seg[2] = 4; 24 assert(seg[0..3].sum == 4); //max(2, 1, 4) == 4 25 26 //[2, 1, 5] 27 seg[2] = 5; 28 assert(seg[0..2].sum == 2); //max(2, 1) == 2 29 assert(seg[0..3].sum == 5); //max(2, 1, 5) == 5 30 31 //[2, 11, 5] 32 seg[1] = seg[1] + 10; 33 assert(seg[0..3].sum == 11); 34 } 35 36 struct SimpleSegEngine(T, alias opTT, T eT) { 37 alias DataType = T; 38 alias LazyType = void; 39 alias BinSearch = binSearchSimple; 40 uint n, sz, lg; 41 T[] d; 42 @property uint length() const {return n;} 43 this(uint n) { 44 import std.algorithm : each; 45 this.n = n; 46 while ((2^^lg) < n) lg++; 47 sz = 2^^lg; 48 d = new T[](2*sz); 49 d.each!((ref x) => x = eT); 50 } 51 this(T[] first) { 52 import std.conv : to; 53 import std.algorithm : each; 54 n = first.length.to!uint; 55 if (n == 0) return; 56 while ((2^^lg) < n) lg++; 57 sz = 2^^lg; 58 d = new T[](2*sz); 59 d.each!((ref x) => x = eT); 60 foreach (i; 0..n) { 61 d[sz+i] = first[i]; 62 } 63 foreach_reverse (i; 1..sz) { 64 update(i); 65 } 66 } 67 pragma(inline): 68 void update(uint k) { 69 d[k] = opTT(d[2*k], d[2*k+1]); 70 } 71 T single(uint k) { 72 return d[k+sz]; 73 } 74 void singleSet(uint k, T x) { 75 k += sz; 76 d[k] = x; 77 foreach (uint i; 1..lg+1) { 78 update(k>>i); 79 } 80 } 81 T sum(uint a, uint b) { 82 assert(0 <= a && a <= b && b <= n); 83 T sml = eT, smr = eT; 84 a += sz; b += sz; 85 while (a < b) { 86 if (a & 1) sml = opTT(sml, d[a++]); 87 if (b & 1) smr = opTT(d[--b], smr); 88 a >>= 1; b >>= 1; 89 } 90 return opTT(sml, smr); 91 } 92 } 93 94 int binSearchSimple(bool rev, alias pred, TR)(TR t, int a, int b) { 95 import std.traits : TemplateArgsOf; 96 alias args = TemplateArgsOf!TR; 97 alias opTT = args[1]; 98 auto x = args[2]; 99 with (t) { 100 static if (!rev) { 101 //left 102 if (pred(x)) return a-1; 103 int pos = a; 104 void f(int a, int b, int l, int r, int k) { 105 if (b <= l || r <= a) return; 106 if (a <= l && r <= b && !pred(opTT(x, d[k]))) { 107 x = opTT(x, d[k]); 108 pos = r; 109 return; 110 } 111 if (l+1 == r) return; 112 int md = (l+r)/2; 113 f(a, b, l, md, 2*k); 114 if (pos >= md) f(a, b, md, r, 2*k+1); 115 } 116 f(a, b, 0, sz, 1); 117 return pos; 118 } else { 119 //right 120 if (pred(x)) return b; 121 int pos = b-1; 122 void f(int a, int b, int l, int r, int k) { 123 if (b <= l || r <= a) return; 124 if (a <= l && r <= b && !pred(opTT(x, d[k]))) { 125 x = opTT(d[k], x); 126 pos = l-1; 127 return; 128 } 129 if (l+1 == r) return; 130 int md = (l+r)/2; 131 f(a, b, md, r, 2*k+1); 132 if (pos < md) f(a, b, l, md, 2*k); 133 } 134 f(a, b, 0, sz, 1); 135 return pos; 136 } 137 } 138 } 139