1 module dkh.segtree.primitive; 2 3 import std.conv : to; 4 5 struct SegTree(alias E, Args...) { 6 import std.traits : ReturnType; 7 alias Engine = E!Args; 8 alias T = Engine.DataType; 9 alias L = Engine.LazyType; 10 11 Engine eng; 12 13 this(size_t n) { eng = Engine(n.to!uint); } 14 this(T[] first) { eng = Engine(first); } 15 16 @property size_t length() const { return eng.length(); } 17 @property size_t opDollar() const { return eng.length(); } 18 19 struct Range { 20 Engine* eng; 21 size_t start, end; 22 @property const(T) sum() { 23 return eng.sum(start.to!uint, end.to!uint); 24 } 25 } 26 const(T) opIndex(size_t k) { 27 assert(0 <= k && k < eng.length()); 28 return eng.single(k.to!uint); 29 } 30 void opIndexAssign(T x, size_t k) { 31 assert(0 <= k && k < eng.length()); 32 eng.singleSet(k.to!uint, x); 33 } 34 size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) { 35 assert(0 <= start && start <= end && end <= eng.length()); 36 return [start, end]; 37 } 38 Range opIndex(size_t[2] rng) { 39 return Range(&eng, rng[0].to!uint, rng[1].to!uint); 40 } 41 static if (!is(L == void)) { 42 void opIndexOpAssign(string op : "+")(L x, size_t[2] rng) { 43 eng.add(rng[0].to!uint, rng[1].to!uint, x); 44 } 45 } 46 } 47 48 import std.traits : isInstanceOf; 49 50 ptrdiff_t binSearchLeft(alias pred, TR)(TR t, ptrdiff_t a, ptrdiff_t b) 51 if (isInstanceOf!(SegTree, TR)) { 52 return TR.Engine.BinSearch!(false, pred)(t.eng, a.to!int, b.to!int); 53 } 54 55 ptrdiff_t binSearchRight(alias pred, TR)(TR t, ptrdiff_t a, ptrdiff_t b) 56 if (isInstanceOf!(SegTree, TR)) { 57 return TR.Engine.BinSearch!(true, pred)(t.eng, a.to!int, b.to!int); 58 }