П'ятниця, 26.04.2024, 11:27
Гость

Мішатронік

Мобільна версія | Додати у вибране  | Мій профіль | Вихід | RSS |
Меню сайту
Наше опитування
Вам легко дається програмування
Всього відповідей: 2
Статистика

Онлайн всього: 1
Гостей: 1
Користувачів: 0


Дерево Фенвика предоставляет возможность хранить массив A[0]... A[N-1] и извлекать/менять его содержимое по следующему интерфейсу:

  • sum(i) — сумма элементов A[0] + A[1] + ... +A[i]
  • change(i, v) — выполнить действие A[i] += v 

Ниже представлен код с реализацией этого интерфейса:

  • dummy — простейшая реализация интерфейса "в лоб"
  • ftree — дерево Фенвика
  • bctree — двоичный контейнер.

#include "macros.h"

struct dummy {
   vi A;
   dummy(int N) : A(vi(N, 0)) {
   }
   void change(int i, int v) {
      A[i] += v;
   }
   int sum(int i) {
      return accumulate(A.begin(), A.begin() + i + 1, 0);
   }
};

struct ftree {
   vi B;
   ftree(int N) : B(vi(N, 0)) {
   }
   void change(int i, int v) {
      B[i] += v;
      int mask = 1;
      while(true) {
         if(!(i & mask)) {
            i |= mask;
            if(i >= sz(B)) {
               break;
            }
            B[i] += v;
         }
         mask <<= 1;
      }
   }
   int sum(int i) {
      int r = 0;
      while(i >= 0) {
         r += B[i];
         i = (i&(i+1))-1;
      }
      return r;
   }
};

struct ftree2 {
   vi B;
   ftree2(int N) : B(vi(N, 0)) { }
   void change(int i, int v) { while(B[i] += v, i |= i+1, i < sz(B)); }
   int sum(int i) { int r = 0; while(i >= 0) r += B[i], i = (i&(i+1))-1; return r; }
};

struct bctree {
   vi C;
   int O;
   bctree(int _N) {
      int N = 1;
      while(N < _N) N *= 2;
      C = vi(N*2);
      O = N;
   }

   void rec_change(int i, int v) {
      if(i > 0) {
         C[i] += v;
         rec_change(i/2, v);
      }
   }
   void change(int i, int v) {
      rec_change(O+i, v);
   }

   int rec_sum(int i) {
      if(i > 1) {
         return (i%2 ? C[i-1] : 0) + rec_sum(i/2);
      }
      else {
         return 0;
      }
   }

   int sum(int i) {
      return C[O+i] + rec_sum(O+i);
   }
};

struct bctree2 {
   vi C;
   int O;
   bctree2(int _N) {
      int N = 1;
      while(N < _N) N *= 2;
      C = vi(N*2);
      O = N;
   }

   void change(int i, int v) {
      i += O;
      while(i > 0) {
         C[i] += v;
         i /= 2;
      }
   }

   int sum(int i) {

      i += O;

      int res = C[i];

      while(i > 1) {
         if(i%2) res += C[i-1];
         i /= 2;
      }

      return res;
   }
};

struct bctree3 {
   vi C;
   int O;
   bctree3(int _N) {
      int N = 1;
      while(N < _N) N *= 2;
      C = vi(N*2);
      O = N;
   }
   void change(int i, int v) {
      i += O;
      while(C[i] += v, i /= 2);
   }
   int sum(int i) {
      i += O;
      int res = C[i];
      while((i%2 ? res += C[i-1] : 0), i /= 2);
      return res;
   }
};

struct bctree4 {
   vi C;
   int O;
   bctree4(int _N) {
      int N = _N;
      // These two lines may not be commented!
      //int N = 1;
      //while(N < _N) N *= 2;
      C = vi(N*2);
      O = N;
   }
   void change(int i, int v) {
      i += O;
      while(C[i] += v, i /= 2);
   }
   int sum(int i) {
      i += O;
      int res = C[i];
      while((i%2 ? res += C[i-1] : 0), i /= 2);
      return res;
   }
};

template<typename T1, typename T2> void test_ftree(int N = 1000) {
   T1 o1(N);
   T2 o2(N);
   loop(t, 1000) {
      int i = rand() % N;
      int v = (rand() % 201) - 100;
      o1.change(i, v);
      o2.change(i, v);
      int k = rand()%N;
      if(o1.sum(k) != o2.sum(k)) {
         L("Test failed!\n");
      }
   }
   L("Test passed.\n");
}

int main() {
   L("ftree test\n");
   //test_ftree<dummy, ftree>();
   //test_ftree<ftree, ftree2>();
   //test_ftree<dummy, ftree2>();
   test_ftree<ftree2, bctree>();
   test_ftree<ftree2, bctree2>();
   test_ftree<ftree, bctree3>();
   test_ftree<ftree, bctree4>(1024);
}

Файл macros.h с макросами STL 

/* macros.h */

typedef vector< int > vi;
typedef vector < vector<int> > vii;

/* forall macro for GCC: */
#define forall(i, v) for( typeof(v.begin()) i = v.begin(); i != v.end() ; i++ )

/* forall macro for others */
#define forall2(i, v, type) for( type::iterator i = v.begin(); i != v.end() ; i++ )

#define all(v) v.begin(),v.end()

#define loop(i, n) for(int i = 0; i < n; i++)
#define pb push_back
#define sz(v) int(v.size())

 

#define belongs(x, c) (find((c).begin(), (c).end(), x) != (c).end())

// operator EQUAL for floating point.
#define EPS 1e-7
#define LEPS 1e-7
typedef long double ldouble
template<typename T> inline bool eq(T a, T b) { return a == b; }
inline bool eq(double a, double b) { return fabs(a-b) < EPS; }
inline bool eq(ldouble a, ldouble b) { return fabsl(a-b) < LEPS; }
inline bool eq(double a, ldouble b) { return fabsl(ldouble(a)-b) < EPS; }
inline bool eq(ldouble a, double b) { return fabsl(a-ldouble(b)) < EPS; }

template<typename T1, typename T2> 
inline bool eq(T1 a, T2 b) { T1 _b = b; return eq(a, _b); }

 

 

Форма входа
Пошук
Друзі сайту
Календар
«  Квітень 2024  »
ПнВтСрЧтПтСбНд
1234567
891011121314
15161718192021
22232425262728
2930

Єдина Країна! Единая Страна!