Варианты дерева Фенвика: различия между версиями

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
Нет описания правки
Строка 1: Строка 1:
== Одномерное дерево Фенвика ==
== Одномерное дерево Фенвика ==


  int a[MAX_SIZE];
  int f[MAX_SIZE];
   
   
  int alpha(int x) {
  int query(int r) {
     int res = 0;
     int res = 0;
     for (int i = x; i >= 0; i = (i & (i + 1)) - 1)
     for (int i = r; i >= 0; i = (i & (i + 1)) - 1)
         res += a[i];
         res += f[i];
     return res;
     return res;
  }
  }
   
   
  void modifyAlphas(int x, int val) {
  void modify(int r, int val) {
     for (int i = x; i < MAX_SIZE; i |= i + 1)
     for (int i = r; i < MAX_SIZE; i |= i + 1)
         a[i] += val;
         f[i] += val;
  }
  }


=== Запрос суммы на отрезке, изменение отдельных элементов ===
=== Запрос суммы на отрезке, изменение отдельных элементов ===
<tt>alpha(x)</tt> &mdash; сумма элементов от <tt>0</tt>-го до <tt>x</tt>-го.
query(r) &mdash; сумма элементов от 0-го до r-го.


  int sum(int x) {
  int prefixSum(int r) {
     return alpha(x);
     return query(r);
  }
  }
   
   
  void add(int x, int val) {
  void add(int pos, int val) {
     modifyAlphas(x, val);
     modify(pos, val);
  }
  }


=== Запрос значений отдельных элементов, изменение на отрезке ===
=== Запрос значений отдельных элементов, изменение на отрезке ===
<tt>alpha(x)</tt> &mdash; значение <tt>x</tt>-го элемента.
query(r) &mdash; значение r-го элемента.


  int get(int x) {
  int get(int pos) {
     return alpha(x);
     return query(pos);
  }
  }
   
   
  void add(int l, int r, int val) {
  void add(int l, int r, int val) {
     modifyAlphas(l, val);
     modify(l, val);
     modifyAlphas(r + 1, -val);
     modify(r + 1, -val);
  }
  }


=== Запрос суммы на отрезке, изменение на отрезке ===
=== Запрос суммы на отрезке, изменение на отрезке ===
<tt>beta(x) * x + alpha(x)</tt> &mdash; сумма элементов от <tt>0</tt>-го до <tt>x</tt>-го.
Tx.query(r) * r + T.query(r) &mdash; сумма элементов от 0-го до r-го.
[[Файл:fenwick_range_1d.png|thumb|right|360px]]
[[Файл:fenwick_range_1d.png|thumb|right|360px]]
  int sum(int x) {
  int prefixSum(int r) {
     return beta(x) * x + alpha(x);
     return Tx.query(r) * r + T.query(r);
  }
  }
   
   
  void add(int l, int r, int val) {
  void add(int l, int r, int val) {
     modifyBetas(l, val);
     Tx.modify(l, val);
     modifyAlphas(l, val * (-l + 1));
     Tx.modify(r + 1, -val);
     modifyBetas(r + 1, -val);
    T.modify(l, val * (-l + 1));
    modifyAlphas(r + 1, val * r);
     T.modify(r + 1, val * r);
  }
  }


== Двумерное дерево Фенвика ==
== Двумерное дерево Фенвика ==


  int a[MAX_SIZE][MAX_SIZE];
  int f[MAX_SIZE][MAX_SIZE];
   
   
  int alpha(int x, int y) {
  int query(int ry, int rx) {
     int res = 0;
     int res = 0;
     for (int i = x; i >= 0; i = (i & (i + 1)) - 1)
     for (int i = ry; i >= 0; i = (i & (i + 1)) - 1)
         for (int j = y; j >= 0; j = (j & (j + 1)) - 1)
         for (int j = rx; j >= 0; j = (j & (j + 1)) - 1)
             res += a[i][j];
             res += f[ry][rx];
     return res;
     return res;
  }
  }
   
   
  void modifyAlphas(int x, int y, int val) {
  void modify(int ry, int rx, int val) {
     for (int i = x; i < MAX_SIZE; i |= i + 1)
     for (int i = ry; i < MAX_SIZE; i |= i + 1)
         for (int j = y; j < MAX_SIZE; j |= j + 1)
         for (int j = rx; j < MAX_SIZE; j |= j + 1)
             a[i][j] += val;
             f[i][j] += val;
  }
  }


=== Запрос суммы на прямоугольнике, изменение отдельных элементов ===
=== Запрос суммы на прямоугольнике, изменение отдельных элементов ===
<tt>alpha(x, y)</tt> &mdash; сумма элементов от <tt>(0; 0)</tt>-го до <tt>(x; y)</tt>-го.
query(ry, rx) &mdash; сумма элементов от (0; 0)-го до (ry; rx)-го.


  int sum(int x, int y) {
  int prefixSum(int ry, int rx) {
     return alpha(x, y);
     return query(ry, rx);
  }
  }
   
   
  void add(int x, int y, int val) {
  void add(int ry, int rx, int val) {
     modifyAlphas(x, y, val);
     modify(ry, rx, val);
  }
  }


=== Запрос значений отдельных элементов, изменение на прямоугольнике ===
=== Запрос значений отдельных элементов, изменение на прямоугольнике ===
<tt>alpha(x, y)</tt> &mdash; значение <tt>(x; y)</tt>-го элемента.
query(ry, rx) &mdash; значение (ry; rx)-го элемента.


  int get(int x, int y) {
  int get(int ry, int rx) {
     return alpha(x, y);
     return query(ry, rx);
  }
  }
   
   
  void add(int lx, int rx, int ly, int ry, int val) {
  void add(int ly, int lx, int ry, int rx, int val) {
     modifyAlphas(lx, ly, val);
     modify(ly, lx, val);
     modifyAlphas(lx, ry + 1, -val);
     modify(ry + 1, lx, -val);
     modifyAlphas(rx + 1, ly, -val);
     modify(ly, rx + 1, -val);
     modifyAlphas(rx + 1, ry + 1, val);
     modify(ry + 1, rx + 1, val);
  }
  }


=== Запрос суммы на прямоугольнике, изменение на прямоугольнике ===
=== Запрос суммы на прямоугольнике, изменение на прямоугольнике ===
<tt>delta(x, y) * x * y + gamma(x, y) * y + beta(x, y) * x + alpha(x, y)</tt> &mdash; сумма элементов от <tt>(0; 0)</tt>-го до <tt>(x; y)</tt>-го.
Tyx.query(ry, rx) * x * y + Ty.query(ry, rx) * y + Tx.query(ry, rx) * x + T.query(ry, rx) &mdash; сумма элементов от (0; 0)-го до (ry; rx)-го.
[[Файл:fenwick_range_2d.png|thumb|right|360px]]
[[Файл:fenwick_range_2d.png|thumb|right|360px]]
  int sum(int x, int y) {
  int prefixSum(int ry, int rx) {
     return delta(x, y) * x * y + gamma(x, y) * y + beta(x, y) * x + alpha(x, y);
     return Tyx.query(ry, rx) * x * y + Ty.query(ry, rx) * y + Tx.query(ry, rx) * x + T.query(ry, rx);
  }
  }
   
   
  void add(int lx, int rx, int ly, int ry, int val) {
  void add(int ly, int lx, int ry, int rx, int val) {
     modifyDeltas(lx, ly, val);
     Tyx.modify(ly, lx, val);
     modifyGammas(lx, ly, val * (-lx + 1));
     Tyx.modify(ry + 1, lx, -val);
     modifyBetas(lx, ly, val * (-ly + 1));
    Tyx.modify(ly, rx + 1, -val);
     modifyAlphas(lx, ly, val * (-lx + 1) * (-ly + 1));
    Tyx.modify(ry + 1, rx + 1, val);
      
     modifyDeltas(lx, ry + 1, -val);
    Ty.modify(ly, lx, val * (-lx + 1));
     modifyGammas(lx, ry + 1, -val * (-lx + 1));
     Ty.modify(ry + 1, lx, -val * (-lx + 1));
     modifyBetas(lx, ry + 1, val * ry);
    Ty.modify(ly, rx + 1, val * rx);
     modifyAlphas(lx, ry + 1, val * (-lx + 1) * ry);
     Ty.modify(ry + 1, rx + 1, -val * rx);
      
     modifyDeltas(rx + 1, ly, -val);
    Tx.modify(ly, lx, val * (-ly + 1));
     modifyGammas(rx + 1, ly, val * rx);
     Tx.modify(ry + 1, lx, val * ry);
    modifyBetas(rx + 1, ly, -val * (-ly + 1));
     Tx.modify(ly, rx + 1, -val * (-ly + 1));
     modifyAlphas(rx + 1, ly, val * rx * (-ly + 1));
     Tx.modify(ry + 1, rx + 1, -val * ry);
      
     modifyDeltas(rx + 1, ry + 1, val);
    T.modify(ly, lx, val * (-lx + 1) * (-ly + 1));
    modifyGammas(rx + 1, ry + 1, -val * rx);
     T.modify(ry + 1, lx val * (-lx + 1) * ry);
    modifyBetas(rx + 1, ry + 1, -val * ry);
     T.modify(ly, rx + 1, val * rx * (-ly + 1));
     modifyAlphas(rx + 1, ry + 1, val * rx * ry);
     T.modify(ry + 1, rx + 1, val * rx * ry);
  }
  }


== Ссылки ==
== Ссылки ==
* [[Дерево Фенвика]]
* [[Дерево Фенвика]]
* [[Дерево Фенвика с модификацией на отрезке]]
* [http://arxiv.org/pdf/1311.6093v4.pdf Mishra P. A New Algorithm for Updating and Querying Sub-arrays of Multidimensional Arrays]
* [http://arxiv.org/pdf/1311.6093v4.pdf Mishra P. A New Algorithm for Updating and Querying Sub-arrays of Multidimensional Arrays]


[[Category:Структуры данных для задач RSQ/RMQ]]
[[Category:Структуры данных для задач RSQ/RMQ]]

Версия от 23:34, 22 июня 2016

Одномерное дерево Фенвика

int f[MAX_SIZE];

int query(int r) {
    int res = 0;
    for (int i = r; i >= 0; i = (i & (i + 1)) - 1)
        res += f[i];
    return res;
}

void modify(int r, int val) {
    for (int i = r; i < MAX_SIZE; i |= i + 1)
        f[i] += val;
}

Запрос суммы на отрезке, изменение отдельных элементов

query(r) — сумма элементов от 0-го до r-го.

int prefixSum(int r) {
    return query(r);
}

void add(int pos, int val) {
    modify(pos, val);
}

Запрос значений отдельных элементов, изменение на отрезке

query(r) — значение r-го элемента.

int get(int pos) {
    return query(pos);
}

void add(int l, int r, int val) {
    modify(l, val);
    modify(r + 1, -val);
}

Запрос суммы на отрезке, изменение на отрезке

Tx.query(r) * r + T.query(r) — сумма элементов от 0-го до r-го.

Fenwick range 1d.png
int prefixSum(int r) {
    return Tx.query(r) * r + T.query(r);
}

void add(int l, int r, int val) {
    Tx.modify(l, val);
    Tx.modify(r + 1, -val);
    T.modify(l, val * (-l + 1));
    T.modify(r + 1, val * r);
}

Двумерное дерево Фенвика

int f[MAX_SIZE][MAX_SIZE];

int query(int ry, int rx) {
    int res = 0;
    for (int i = ry; i >= 0; i = (i & (i + 1)) - 1)
        for (int j = rx; j >= 0; j = (j & (j + 1)) - 1)
            res += f[ry][rx];
    return res;
}

void modify(int ry, int rx, int val) {
    for (int i = ry; i < MAX_SIZE; i |= i + 1)
        for (int j = rx; j < MAX_SIZE; j |= j + 1)
            f[i][j] += val;
}

Запрос суммы на прямоугольнике, изменение отдельных элементов

query(ry, rx) — сумма элементов от (0; 0)-го до (ry; rx)-го.

int prefixSum(int ry, int rx) {
    return query(ry, rx);
}

void add(int ry, int rx, int val) {
    modify(ry, rx, val);
}

Запрос значений отдельных элементов, изменение на прямоугольнике

query(ry, rx) — значение (ry; rx)-го элемента.

int get(int ry, int rx) {
    return query(ry, rx);
}

void add(int ly, int lx, int ry, int rx, int val) {
    modify(ly, lx, val);
    modify(ry + 1, lx, -val);
    modify(ly, rx + 1, -val);
    modify(ry + 1, rx + 1, val);
}

Запрос суммы на прямоугольнике, изменение на прямоугольнике

Tyx.query(ry, rx) * x * y + Ty.query(ry, rx) * y + Tx.query(ry, rx) * x + T.query(ry, rx) — сумма элементов от (0; 0)-го до (ry; rx)-го.

Fenwick range 2d.png
int prefixSum(int ry, int rx) {
    return Tyx.query(ry, rx) * x * y + Ty.query(ry, rx) * y + Tx.query(ry, rx) * x + T.query(ry, rx);
}

void add(int ly, int lx, int ry, int rx, int val) {
    Tyx.modify(ly, lx, val);
    Tyx.modify(ry + 1, lx, -val);
    Tyx.modify(ly, rx + 1, -val);
    Tyx.modify(ry + 1, rx + 1, val);
    
    Ty.modify(ly, lx, val * (-lx + 1));
    Ty.modify(ry + 1, lx, -val * (-lx + 1));
    Ty.modify(ly, rx + 1, val * rx);
    Ty.modify(ry + 1, rx + 1, -val * rx);
    
    Tx.modify(ly, lx, val * (-ly + 1));
    Tx.modify(ry + 1, lx, val * ry);
    Tx.modify(ly, rx + 1, -val * (-ly + 1));
    Tx.modify(ry + 1, rx + 1, -val * ry);
    
    T.modify(ly, lx, val * (-lx + 1) * (-ly + 1));
    T.modify(ry + 1, lx val * (-lx + 1) * ry);
    T.modify(ly, rx + 1, val * rx * (-ly + 1));
    T.modify(ry + 1, rx + 1, val * rx * ry);
}

Ссылки