981377660LMT / ts

ts学习
6 stars 1 forks source link

SegmentTreeDivideAndConquerUndo 的重构:需要的时候,再取值 #436

Open 981377660LMT opened 7 months ago

981377660LMT commented 7 months ago

重构前,构造函数中需要传入三个函数:

  /**
   * dfs 遍历整棵线段树来得到每个时间点的答案.
   * @param mutate 添加编号为`mutationId`的变更后产生的副作用.
   * @param undo 撤销一次`mutate`操作.
   * @param query 响应编号为`queryId`的查询.
   * @complexity 一共调用 **O(nlogn)** 次`mutate`和`undo`,**O(q)** 次`query`.
   */
  constructor(
    mutate: (mutationId: number) => void,
    undo: () => void,
    query: (queryId: number) => void
  )
  constructor(
    options: {
      mutate: (mutationId: number) => void
      undo: () => void
      query: (queryId: number) => void
    } & ThisType<void>
  )
  constructor(arg1: any, arg2?: any, arg3?: any) {
    if (typeof arg1 === 'object') {
      this._mutate = arg1.mutate
      this._undo = arg1.undo
      this._query = arg1.query
    } else {
      this._mutate = arg1
      this._undo = arg2
      this._query = arg3
    }
  }

导致使用的时候,需要先定义函数,再添加查询,非常不方便; 其实可以使用的时候再传入函数:


  /**
   * dfs 遍历整棵线段树来得到每个时间点的答案.
   * @param mutate 添加编号为`mutationId`的变更后产生的副作用.
   * @param undo 撤销一次`mutate`操作.
   * @param query 响应编号为`queryId`的查询.
   * @complexity 一共调用 **O(nlogn)** 次`mutate`和`undo`,**O(q)** 次`query`.
   */
  run(mutate: (mutationId: number) => void, undo: () => void, query: (queryId: number) => void): void
  run(
    options: {
      mutate: (mutationId: number) => void
      undo: () => void
      query: (queryId: number) => void
    } & ThisType<void>
  ): void
  run(arg1: any, arg2?: any, arg3?: any): void {
    if (!this._queries.length) return
    if (typeof arg1 === 'object') {
      this._mutate = arg1.mutate
      this._undo = arg1.undo
      this._query = arg1.query
    } else {
      this._mutate = arg1
      this._undo = arg2
      this._query = arg3
    }
981377660LMT commented 7 months ago

这种模式应该可以叫 ”类莫队“,先添加查询,再在 run 函数里执行副作用。

981377660LMT commented 7 months ago

还有一个好处是,防止忘记调用 .run()