2020年4月22日水曜日

【C#】競プロ用にSegmentTreeのライブラリを作ったよ!

SegmentTreeってセグメント木とかセグ木とか色々に呼ばれているので検索するの苦労しません?
あなたはどのワードでここに辿り着きましたか?

先にコードを載せます。超普通のセグ木になります。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. namespace Library
  6. {
  7. public class SegmentTree<T> where T: struct
  8. {
  9. private readonly T[] data;
  10. private int size = 1;
  11. private T defaultValue;
  12. private Func<T, T, T> function;
  13.  
  14. public SegmentTree(int size, T defaultValue, Func<T, T, T> function)
  15. {
  16. while(this.size < size) this.size *= 2;
  17. this.defaultValue = defaultValue;
  18. this.function = function;
  19. data = Enumerable.Repeat(defaultValue, this.size * 2 - 1).ToArray();
  20. }
  21.  
  22. // [a, b)
  23. public T RangedValue(int a, int b) { return RangedValue(a, b, 0, 0, size); }
  24.  
  25. private T RangedValue(int a, int b, int now, int l, int r)
  26. {
  27. if (r <= a || b <= l) return defaultValue;
  28. if (a <= l && r <= b) return data[now];
  29.  
  30. return function(RangedValue(a, b, now * 2 + 1, l, (l + r) / 2), RangedValue(a, b, now * 2 + 2, (l + r) / 2, r));
  31. }
  32.  
  33. public T this[int index]
  34. {
  35. get
  36. {
  37. return data[size + index - 1];
  38. }
  39. set
  40. {
  41. index += size - 1;
  42. data[index] = value;
  43. while (index > 0)
  44. {
  45. index = (index - 1) / 2;
  46. data[index] = function(data[index * 2 + 1], data[index * 2 + 2]);
  47. }
  48. }
  49. }
  50. }
  51. }

以下工夫した点

  • Genericsの型であるTに値型の制約を与えた
  • indexによるアクセスでより直感的に
  • ぐう短い