Cod sursa(job #2934195)

Utilizator highonrocketfuelOverweight Raccoon highonrocketfuel Data 5 noiembrie 2022 17:10:25
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.15 kb
#define maxs(a, b) a = (a > b) ? a : b
#define mins(a, b) a = (a < b) ? a : b

#define all(a) a.begin(), a.end()
#define rng(a, i, j) a.begin() + i, a.begin() + j

#define aall(a, n) a + 1, a + 1 + n
#define arng(a, i, j) a + i, a + j

#define pb push_back
#define ins insert
#define sz(a) (int)a.size()

#define rs inFile
#define ws outFile

#include <algorithm>
#include <fstream>
#include <iostream>

const int NMAX = 1e5;

int n;
int a[1 + NMAX];

int seg_tree[1 + 2 * NMAX];

int st_join(int value_left, int value_right) {
  return std::max(value_left, value_right);
}

void st_build(int index = 1, int left = 1, int right = n) {
  // leaf node | interval contains only one number
  if (left == right) {
    seg_tree[index] = a[left];

    return;
  }

  int midpoint = (left + right) >> 1;
  int left_child = 2 * index;
  int right_child = 2 * index + 1;

  st_build(left_child, left, midpoint);
  st_build(right_child, midpoint + 1, right);

  seg_tree[index] = st_join(seg_tree[left_child], seg_tree[right_child]);
}

void st_point_update(int point_index, int new_value, int index = 1,
                     int left = 1, int right = n) {
  // if we got to the leaf, it must be the correct one
  if (left == right) {
    seg_tree[index] = new_value;

    return;
  }

  // if we haven't got to the leaf yet, go deeper one level
  int midpoint = (left + right) >> 1;
  int left_child = 2 * index;
  int right_child = 2 * index + 1;

  if (point_index <= midpoint) {
    st_point_update(point_index, new_value, left_child, left, midpoint);
  } else {
    st_point_update(point_index, new_value, right_child, midpoint + 1, right);
  }

  seg_tree[index] = st_join(seg_tree[left_child], seg_tree[right_child]);
}

int st_range_query(int range_left, int range_right, int index = 1, int left = 1,
                   int right = n) {
  // check if current interval is completely outside of the target interval
  if (right < range_left || left > range_right) {
    return 0;  // neutral element for st_join()
  }

  // check if current interval is completely inside of the target interval
  if (range_left <= left && right <= range_right) {
    return seg_tree[index];
  }

  // if none, split the query in two different halves
  int midpoint = (left + right) >> 1;
  int left_child = 2 * index;
  int right_child = 2 * index + 1;

  int left_result =
      st_range_query(range_left, range_right, left_child, left, midpoint);

  int right_result =
      st_range_query(range_left, range_right, right_child, midpoint + 1, right);

  return st_join(left_result, right_result);
}

int main() {
  std::ifstream inFile("arbint.in");
  std::ofstream outFile("arbint.out");

  int q;
  rs >> n >> q;

  for (int i = 1; i <= n; ++i) {
    rs >> a[i];
  }

  st_build();

  while (q--) {
    int type;
    rs >> type;

    if (type == 0) {
      int left, right;
      rs >> left >> right;

      int result = st_range_query(left, right);
      ws << result << '\n';
    } else {
      int index, new_value;
      rs >> index >> new_value;

      st_point_update(index, new_value);
    }
  }

  return 0;
}