1 module dkh.datastructure.segtreenaive; 2 3 import dkh.datastructure.segtree; 4 5 /* 6 This file contain naive codes of segtree, you don't need to import this file usually. 7 If you want to use segtree, import dkh.dasatructure.segtree. 8 */ 9 10 import std.conv : to; 11 import std.functional : binaryFun; 12 import std.traits : isInstanceOf; 13 14 static struct NaiveSimple(T, alias opTT, T eT) { 15 import std.conv : to; 16 alias DataType = T; 17 alias LazyType = void; 18 alias BinSearch = binSearchNaiveSimple; 19 T[] d; 20 @property size_t length() const { return d.length; } 21 this(uint n) { 22 d = new T[n]; 23 } 24 this(T[] first) { 25 d = first.dup; 26 } 27 const(T) sum(uint l, uint r) { 28 T sm = eT; 29 foreach (i; l..r) { 30 sm = opTT(sm, d[i]); 31 } 32 return sm; 33 } 34 const(T) single(int k) { return d[k]; } 35 void singleSet(int k, in T x) { d[k] = x; } 36 } 37 38 static struct NaiveLazy(T, L, alias opTT, alias opTL, alias opLL, T eT, L eL) { 39 import std.conv : to; 40 alias DataType = T; 41 alias LazyType = L; 42 alias BinSearch = binSearchNaiveLazy; 43 T[] d; 44 @property size_t length() const { return d.length; } 45 this(uint n) { 46 d = new T[n]; 47 } 48 this(T[] first) { 49 d = first.dup; 50 } 51 const(T) sum(uint l, uint r) { 52 T sm = eT; 53 foreach (i; l..r) { 54 sm = opTT(sm, d[i]); 55 } 56 return sm; 57 } 58 void add(uint l, uint r, in L m) { 59 foreach (i; l..r) { 60 d[i] = opTL(d[i], m); 61 } 62 } 63 const(T) single(int k) { return d[k]; } 64 void singleSet(int k, in T x) { d[k] = x; } 65 } 66 67 68 int binSearchNaiveSimple(bool rev, alias pred, TR)(TR t, int a, int b) { 69 import std.traits : TemplateArgsOf; 70 alias args = TemplateArgsOf!TR; 71 alias opTT = args[1]; 72 auto x = args[2]; 73 with (t) { 74 static if (!rev) { 75 //left 76 if (pred(x)) return a-1; 77 foreach (i; a..b) { 78 x = opTT(x, d[i]); 79 if (pred(x)) return i; 80 } 81 return b; 82 } else { 83 if (pred(x)) return b; 84 foreach_reverse (i; a..b) { 85 x = opTT(d[i], x); 86 if (pred(x)) return i; 87 } 88 return a-1; 89 } 90 } 91 } 92 93 int binSearchNaiveLazy(bool rev, alias pred, TR)(TR t, int a, int b) { 94 import std.traits : TemplateArgsOf; 95 alias args = TemplateArgsOf!TR; 96 alias opTT = args[2]; 97 auto x = args[5]; 98 with (t) { 99 static if (!rev) { 100 //left 101 if (pred(x)) return a-1; 102 foreach (i; a..b) { 103 x = opTT(x, d[i]); 104 if (pred(x)) return i; 105 } 106 return b; 107 } else { 108 if (pred(x)) return b; 109 foreach_reverse (i; a..b) { 110 x = opTT(d[i], x); 111 if (pred(x)) return i; 112 } 113 return a-1; 114 } 115 } 116 } 117 118 unittest { 119 import std.traits : AliasSeq; 120 alias SimpleEngines = AliasSeq!(SimpleSegEngine); 121 alias LazyEngines = AliasSeq!(LazySegEngine); 122 123 import std.random; 124 125 void f(alias T)() { 126 auto nav = LazySeg!(uint, uint, 127 (a, b) => (a | b), 128 (a, b) => (a | b), 129 (a, b) => (a | b), 130 0U, 0U, NaiveLazy)(100); 131 auto seg = LazySeg!(uint, uint, 132 (a, b) => (a | b), 133 (a, b) => (a | b), 134 (a, b) => (a | b), 135 0U, 0U, T)(100); 136 foreach (i; 0..100) { 137 auto u = uniform!"[]"(0, 31); 138 seg[i] = u; 139 nav[i] = u; 140 } 141 foreach (i; 0..100) { 142 foreach (j; i..101) { 143 foreach (x; 0..32) { 144 assert( 145 nav.binSearchLeft!((a) => a & x)(i, j) == 146 seg.binSearchLeft!((a) => a & x)(i, j)); 147 assert(seg.binSearchLeft!((a) => true)(i, j) == i-1); 148 assert( 149 nav.binSearchRight!((a) => a & x)(i, j) == 150 seg.binSearchRight!((a) => a & x)(i, j)); 151 assert(seg.binSearchRight!((a) => true)(i, j) == j); 152 } 153 } 154 } 155 } 156 void g(alias T)() { 157 auto nav = SimpleSeg!(uint, 158 (a, b) => (a | b), 159 0U, NaiveSimple)(100); 160 auto seg = SimpleSeg!(uint, 161 (a, b) => (a | b), 162 0U, T)(100); 163 foreach (i; 0..100) { 164 auto u = uniform!"[]"(0, 31); 165 seg[i] = u; 166 nav[i] = u; 167 } 168 foreach (i; 0..100) { 169 foreach (j; i..101) { 170 foreach (x; 0..32) { 171 assert( 172 nav.binSearchLeft!((a) => a & x)(i, j) == 173 seg.binSearchLeft!((a) => a & x)(i, j)); 174 assert(seg.binSearchLeft!((a) => true)(i, j) == i-1); 175 assert( 176 nav.binSearchRight!((a) => a & x)(i, j) == 177 seg.binSearchRight!((a) => a & x)(i, j)); 178 assert(seg.binSearchRight!((a) => true)(i, j) == j); 179 } 180 } 181 } 182 } 183 foreach (E; LazyEngines) { 184 f!E(); 185 } 186 foreach (E; SimpleEngines) { 187 g!E(); 188 } 189 } 190 191 unittest { 192 //some func test 193 import std.traits : AliasSeq; 194 alias SimpleEngines = AliasSeq!(SimpleSegEngine); 195 alias LazyEngines = AliasSeq!(LazySegEngine); 196 197 void checkSimple(alias Seg)() { 198 import std.algorithm : max; 199 200 alias S = SegTree!(Seg, int, (a, b) => a+b, 0); 201 S seg; 202 seg = S(10); 203 assert(seg.length == 10); 204 } 205 void check(alias Seg)() { 206 import std.algorithm : max; 207 208 alias S = SegTree!(Seg, int, int, 209 (a, b) => max(a, b), (a, b) => a+b, (a, b) => a+b, 0, 0); 210 S seg; 211 seg = S([2, 1, 4]); 212 213 //[2, 1, 4] 214 seg[0] = 2; seg[1] = 1; seg[2] = 4; 215 assert(seg[0..3].sum == 4); 216 217 //[2, 1, 5] 218 seg[2] = 5; 219 assert(seg[0..2].sum == 2); 220 assert(seg[0..3].sum == 5); 221 222 //[12, 11, 5] 223 seg[0..2] += 10; 224 assert(seg[0..3].sum == 12); 225 226 //n=10 227 auto seg2 = SegTree!(Seg, int, int, 228 (a, b) => max(a, b), (a, b) => a+b, (a, b) => a+b, 0, 0)(10); 229 assert(seg2.length == 10); 230 } 231 232 foreach (E; SimpleEngines) { 233 checkSimple!E(); 234 } 235 foreach (E; LazyEngines) { 236 check!E(); 237 } 238 } 239 240 unittest { 241 //stress test 242 import std.traits : AliasSeq; 243 alias SimpleEngines = AliasSeq!(SimpleSegEngine); 244 alias LazyEngines = AliasSeq!(LazySegEngine); 245 246 import std.typecons, std.random, std.algorithm; 247 import dkh.modint, dkh.matrix, dkh.numeric.primitive; 248 static immutable uint MD = 10^^9 + 7; 249 alias Mint = ModInt!MD; 250 alias Mat = SMatrix!(Mint, 2, 2); 251 252 static immutable Mat e = matrix!(2, 2, (i, j) => Mint(i == j ? 1 : 0))(); 253 254 Xorshift128 gen; 255 256 Mat rndM() { 257 Mat m; 258 while (true) { 259 m = matrix!(2, 2, (i, j) => Mint(uniform(0, MD, gen)))(); 260 if (m[0, 0] * m[1, 1] == m[0, 1] * m[1, 0]) continue; 261 break; 262 } 263 return m; 264 } 265 266 Mat checkSimple(alias Seg)(int N, int M, uint seed) { 267 alias T = Tuple!(Mat, int); 268 gen = Xorshift128(seed); 269 Mat[] a = new Mat[N]; 270 a.each!((ref x) => x = rndM()); 271 alias Q = Tuple!(int, int, int, Mat); 272 Q[] que = new Q[M]; 273 foreach (ref q; que) { 274 q[0] = uniform(0, 2, gen); 275 if (N == 0) q[0] = 0; 276 if (q[0] == 0) { 277 q[1] = uniform(0, N+1, gen); 278 q[2] = uniform(0, N+1, gen); 279 if (q[1] > q[2]) swap(q[1], q[2]); 280 } else { 281 q[1] = uniform(0, N, gen); 282 } 283 q[3] = rndM(); 284 } 285 static auto opTT(Mat a, Mat b) { 286 return a*b; 287 } 288 289 auto s = SegTree!(Seg, Mat, opTT, e)(a); 290 Mat res; 291 foreach (q; que) { 292 if (q[0] == 0) { 293 //sum 294 res += s[q[1]..q[2]].sum(); 295 } else if (q[0] == 1) { 296 //set 297 s[q[1]] = q[3]; 298 } 299 } 300 return res; 301 } 302 Mat check(alias Seg)(int N, int M, uint seed) { 303 alias T = Tuple!(Mat, int); 304 gen = Xorshift128(seed); 305 T[] a = new T[N]; 306 a.each!((ref x) => x = T(rndM(), 1)); 307 alias Q = Tuple!(int, int, int, Mat); 308 Q[] que = new Q[M]; 309 foreach (ref q; que) { 310 q[0] = uniform(0, 4, gen); 311 if (N == 0) q[0] %= 2; 312 if (q[0] < 2) { 313 q[1] = uniform(0, N+1, gen); 314 q[2] = uniform(0, N+1, gen); 315 if (q[1] > q[2]) swap(q[1], q[2]); 316 } else { 317 q[1] = uniform(0, N, gen); 318 } 319 q[3] = rndM(); 320 } 321 static auto opTT(T a, T b) { 322 return T(a[0]*b[0], a[1]+b[1]); 323 } 324 static auto opTL(T a, Mat b) { 325 if (b == Mat()) return a; 326 return T(pow(b, a[1], e), a[1]); 327 } 328 static auto opLL(Mat a, Mat b) { 329 return b; 330 } 331 332 auto s = SegTree!(Seg, T, Mat, opTT, opTL, opLL, T(e, 0), Mat())(a); 333 Mat res; 334 foreach (q; que) { 335 if (q[0] == 0) { 336 //sum 337 res += s[q[1]..q[2]].sum()[0]; 338 } else if (q[0] == 1) { 339 //set 340 s[q[1]..q[2]] += q[3]; 341 } else if (q[0] == 2) { 342 //single sum 343 T w = s[q[1]]; 344 res += w[0]; 345 } else if (q[0] == 3) { 346 //single set 347 s[q[1]] = T(q[3], 1); 348 } 349 } 350 return res; 351 } 352 353 import dkh.stopwatch; 354 StopWatch sw; sw.start; 355 356 int n = 40; 357 Mat[] ansLazy = new Mat[n]; 358 foreach (i; 0..n) { 359 ansLazy[i] = check!NaiveLazy(i, 500, 114514); 360 } 361 Mat[] ansSimple = new Mat[n]; 362 foreach (i; 0..n) { 363 ansSimple[i] = checkSimple!NaiveSimple(i, 500, 114514); 364 } 365 366 foreach (E; SimpleEngines) { 367 foreach (i; 0..n) { 368 assert(checkSimple!E(i, 500, 114514) == ansSimple[i]); 369 } 370 } 371 foreach (E; LazyEngines) { 372 foreach (i; 0..n) { 373 assert(check!E(i, 500, 114514) == ansLazy[i]); 374 } 375 } 376 377 import std.stdio; 378 writeln("SegTree Stress: ", sw.peek.toMsecs); 379 }