Advertisement
PyTimur

Untitled

Nov 18th, 2021
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.93 KB | None | 0 0
  1. #include <iostream>
  2. #include <windows.h> // для отображения кириллицы
  3. using namespace std;
  4.  
  5. int f(int x){ // зануляет блок младших единиц
  6. return x&(x+1);
  7. }
  8.  
  9. int g(int x){ // заединичивает младший ноль
  10. return x|(x+1);
  11. }
  12.  
  13. int Sum(int fw[], int i) {
  14. int res = 0;
  15. for (; i >= 0; i = f(i)-1){
  16. res += fw[i];
  17. }
  18. /* i -> f(i)-1, при этом младший ноль становится единицей и что-то еще в более старших разрядов, но это не существенно
  19. * число шагов не превышает число бит в i т.е. <= log(n)
  20. * когда берем f(i) мы сдвигаем индекс на тот отрезок который мы посчитали, а -1 нужен для, того чтобы посчитать следующий отрезок не включенный в предыдущий
  21. */
  22. return res;
  23. }
  24.  
  25. int getSum(int fw[], int l, int r) {
  26. return Sum(fw, r) - Sum(fw, l - 1);
  27. // берем сумму на префиксе до r, вычтем на префиксе l-1 и получим искомую сумму
  28. }
  29.  
  30. void update(int fw[], int n, int i, int newVal) {
  31. /*
  32. * итераций столько сколько нулей в исходном числе
  33. * т.к в двоичной записи log(n) бит, то и итераций будет log(n)
  34. * Таким образом update и Sum работают за log(n)
  35. */
  36. for (; i < n; i = g(i)){
  37. fw[i] += newVal;
  38. }
  39. /*
  40. * При изменении одного элемента, нам надо изменить все суммы в которые он входит
  41. * Представим себе, что a[pos] увеличивается на val.
  42. * Тогда меняются те fw[i] в отрезке которых есть pos то есть, которые удовлетворяют условию f(i) <= pos <= i
  43. * Т.к для каждого i число fw[i] это сумма на отрезке с f(i) до i, соответственно это сумма может поменяться, если в него попало число a[pos]
  44. * f(i) [ ] 00000
  45. * pos [ ] 0... что угодно
  46. * i [ ] 01111
  47. * Функции g(x) заединичает младший ноль, таким образом мы проходимся по все I-ым элементам и изменяем их
  48. */
  49. }
  50.  
  51. int *build(int a[], int n) {
  52. int *fw = new int[n+1];
  53. for (int i = 0; i <= n; ++i){
  54. fw[i] = 0;
  55. }
  56. /*
  57. * Для того чтобы построить дерево достаточно, взять нулевой массив равный размеру исходного
  58. * и N раз вызвать операцию изменения элемента
  59. */
  60. for (int i = 0; i < n; ++i)
  61. update(fw, n, i, a[i]);
  62.  
  63. return fw;
  64. }
  65.  
  66. int main(){
  67. SetConsoleOutputCP(CP_UTF8); // для отображения кириллицы
  68. int n;
  69. cout << "Введите размер массива:";
  70. cin >> n;
  71. int* a = new int[n];
  72. cout << "Введите элемента массива:";
  73. for (int i = 0; i < n; ++i){
  74. cin >> a[i];
  75. }
  76. a = build(a,n); // строим дерево Фенвика
  77. cout << endl;
  78. cout << "Количество запросов:";
  79. int k;
  80. cin >> k;
  81. for (int i = 0; i < k; ++i){ // обработка запросов
  82. int l,r;
  83. cout << "Введите левую и правую границу отрезка:";
  84. cin >> l >> r;
  85. cout << "Сумма на отрезке равна:" << getSum(a,l-1,r-1) << endl;
  86. cout << endl;
  87. }
  88. delete [] a;
  89. return 0;
  90. }
  91.  
  92.  
  93.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement