Cod sursa(job #2753477)

Utilizator cristi_macoveiMacovei Cristian cristi_macovei Data 22 mai 2021 23:32:55
Problema Arbori indexati binar Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.54 kb
#include <iostream>
#include <fstream>

const int NMAX = 1e5;

int n;
int seg_tree[4 * NMAX];
int a[1 + NMAX];

void build(int index, int left, int right) {
  if (left == right) {
    seg_tree[index] = a[left];
    return;
  }

  int left_child = index * 2;
  int right_child = index * 2 + 1;
  int mid = (left + right) / 2;

  build(left_child, left, mid);
  build(right_child, mid + 1, right);

  seg_tree[index] = seg_tree[left_child] + seg_tree[right_child];
}

void print_seg_tree(int index, int left, int right) {
  std::printf("index : %d, interval (%d, %d), value : %d\n", index, left, right, seg_tree[index]);

  if (left == right) {
    return;
  }

  int left_child = index * 2;
  int right_child = index * 2 + 1;
  int mid = (left + right) / 2;

  print_seg_tree(left_child, left, mid);
  print_seg_tree(right_child, mid + 1, right);
}

void point_update(int index, int left, int right, int target_index, int update_value) {
  if (left == right) {
    if (left != target_index)
      exit(-147);

    seg_tree[index] += update_value;
    return;
  }

  int left_child = 2 * index;
  int right_child = 2 * index + 1;
  int mid = (left + right) / 2;

  if (mid >= target_index)
    point_update(left_child, left, mid, target_index, update_value);
  else
    point_update(right_child, mid + 1, right, target_index, update_value);

  seg_tree[index] = seg_tree[left_child] + seg_tree[right_child];
}

int range_query(int index, int left, int right, int query_left, int query_right) {
  if (left == right) {
    if (query_left <= left && left <= query_right)
      return seg_tree[index];
    else
      return 0;
  }

  if (query_left > right || left > query_right)
    return 0;

  if (query_left <= left && right <= query_right)
    return seg_tree[index];

  int left_child = 2 * index;
  int right_child = 2 * index + 1;
  int mid = (left + right) / 2;

  return range_query(left_child, left, mid, query_left, query_right) + range_query(right_child, mid + 1, right, query_left, query_right);
}

int binary_search(int value) {
//  std::printf("searching value %d\n", value);

  int left = 1;
  int right = n;
  int seg_tree_index = 1;

  while (left <= right) {
//    std::printf("at left = %d, right = %d, in seg tree : %d, remaining = %d \n", left, right, seg_tree[seg_tree_index], value);
    if (left == right) {
      if (value != seg_tree[seg_tree_index])
        return -1;

      return left;
    }

    int left_child = seg_tree_index * 2;
    int right_child = seg_tree_index * 2 + 1;
    int mid = (left + right) / 2;

    if (value > seg_tree[left_child]) {
      seg_tree_index = right_child;
      left = mid + 1;
      value -= seg_tree[left_child];
    }
    else {
      seg_tree_index = left_child;
      right = mid;
    }
  }
}

int main() {
  std::ifstream in("aib.in");
  std::ofstream out("aib.out");

  int m;
  in >> n >> m;
  for (int i = 1; i <= n; ++i)
    in >> a[i];

  build(1, 1, n);

  for (int i = 1; i <= m; ++i) {
    int type;
    in >> type;

    switch (type) {
      case 0:
        int index, value;
        in >> index >> value;

//        std::printf("updating %d with + %d\n", index, value);

        point_update(1, 1, n, index, value);

//        std::cout << "DEBUG..\n";
//        print_seg_tree(1, 1, n);
//        std::cout << "END..\n";

        break;

      case 1:
        int left, right;
        in >> left >> right;

        out << range_query(1, 1, n, left, right) << '\n';

        break;

      case 2:
        int sum;
        in >> sum;

        out << binary_search(sum) << '\n';

        break;

      default:
        exit(-209);
    }
  }
  return 0;
}