Cod sursa(job #2209997)

Utilizator mlc_oficialBoris Barca mlc_oficial Data 5 iunie 2018 13:41:21
Problema Arbori indexati binar Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.16 kb
#include <iostream>
#include <algorithm>
#include <vector>

namespace algo {

template <typename T>
struct BinaryPlus {
  T identity() const                            { return T(); }
  T operator()(const T lhs, const T rhs) const  { return lhs + rhs; }
  T negate(const T x) const                     { return -x; }
  T times(const T x, const int num_times) const { return x * num_times; }
};

template <typename T, typename Op = BinaryPlus<T>>
class FenwickTree {
 public:
  FenwickTree(const int n=0) : tree_(n) {}
  FenwickTree(const std::vector<T>& v) {
    int n = static_cast<int>(v.size());
    tree_.assign(n, operation_.identity());
    for (int i = 0; i < n; ++i) {
      tree_[i] = operation_(tree_[i], v[i]);
      if ((i | (i + 1)) < n) {
        tree_[i | (i + 1)] = operation_(tree_[i | (i + 1)], tree_[i]);
      }
    }
  }

  void Add(int idx, const T value) {
    while (idx < static_cast<int>(tree_.size())) {
      tree_[idx] = operation_(tree_[idx], value);
      idx       |= idx + 1;
    }
  }

  T Query(int idx) const {
    T answer = operation_.identity();
    while (idx >= 0) {
      answer = operation_(tree_[idx], answer);
      idx    = (idx & (idx + 1)) - 1;
    }
    return answer;
  }

  T Query(const int left_idx, const int right_idx) const {
    return operation_(Query(right_idx), operation_.negate(Query(left_idx - 1)));
  }

  T PointValue(int idx) const {
    T answer = tree_[idx];
    if (idx > 0) {
      const int to = (idx & (idx + 1)) - 1;
      --idx;
      while (idx != to) {
        answer = operation_(answer, operation_.negate(tree_[idx]));
        idx    = (idx & (idx + 1)) - 1;
      }
    }
    return answer;
  }

  void Set(int idx, const T value) {
    Add(idx, operation_(operation_.negate(PointValue(idx)), value));
  }

  int LowerBound(T sum) const {
    sum = operation_(sum, operation_.negate(1));
    int idx = -1;
    for (int step = 1 << (31 - __builtin_clz(tree_.size()));
         step; step >>= 1) {
      if (idx + step < static_cast<int>(tree_.size())
          && tree_[idx + step] <= sum) {
        idx += step;
        sum  = operation_(sum, operation_.negate(tree_[idx]));
      }
    }
    return idx + 1;
  }

 private:
  std::vector<T> tree_;
  Op operation_;
};

}  // namespace algo

int main() 
{
    #ifdef INFOARENA
    freopen("aib.in", "r", stdin);
    freopen("aib.out", "w", stdout);
    #endif
    
    int n, m;
    scanf("%d%d", &n, &m);
    std::vector<int> v(n);
    for (auto& it : v) {
        scanf("%d", &it);
    }
    
    algo::FenwickTree<int> ft(v);
    while (m--> 0) {
        int op_type;
        scanf("%d", &op_type);
        if (op_type == 0) {
            int pos, value;
            scanf("%d%d", &pos, &value); 
            --pos;
            ft.Add(pos, value);
        } else if (op_type == 1) {
            int lhs, rhs;
            scanf("%d%d", &lhs, &rhs);
            --lhs; --rhs;
            printf("%d\n", ft.Query(lhs, rhs));
        } else {
            int sum;
            scanf("%d", &sum);
            printf("%d\n", ft.LowerBound(sum) + 1);
        }
    }
    
    return 0;
}