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