Submission #1130129

#TimeUsernameProblemLanguageResultExecution timeMemory
1130129matthewSimple (info1cup19_simple)C++20
100 / 100
577 ms26368 KiB
#include <iostream>
#include <utility>

using ll = long long;
const int MAX_N = 200'000;
const int MAX_LEN = (1 << 18);
const ll INF_LL = 1'000'000'000'000'000'000LL;

struct MinMax {
  ll min, max;

  MinMax operator +(const MinMax &other) {
    return {
      std::min(min, other.min),
      std::max(max, other.max)
    };
  }
};

struct Node {
  ll min[2];
  ll max[2];
  ll lazy;

  Node operator +(const Node &other) {
    return {
      {std::min(min[0], other.min[0]),
       std::min(min[1], other.min[1])},
      {std::max(max[0], other.max[0]),
       std::max(max[1], other.max[1])},
      0
    };
  }
};

struct SegTree {
  int n;
  Node st[2 * MAX_LEN];

  void init(int n, int a[]) {
    this->n = (1 << (32 - __builtin_clz(n - 1)));
    for(int i = 0; i < n; i++) {
      st[i + this->n] = {{INF_LL, INF_LL}, {-1, -1}, 0};
      st[i + this->n].min[a[i] % 2] = st[i + this->n].max[a[i] % 2] = a[i];
    }
    for(int i = n; i < this->n; i++) {
      st[i + this->n] = {{INF_LL, INF_LL}, {-1, -1}, 0};
    }
    for(int i = this->n - 1; i > 0; i--) {
      st[i] = st[2 * i] + st[2 * i + 1];
    }
  }

  void update_node(Node &node, ll val) {
    if(node.min[0] != INF_LL) {
      node.min[0] += val;
    }
    if(node.min[1] != INF_LL) {
      node.min[1] += val;
    }
    if(node.max[0] != -1) {
      node.max[0] += val;
    }
    if(node.max[1] != -1) {
      node.max[1] += val;
    }
    if(val % 2 == 1) {
      std::swap(node.min[0], node.min[1]);
      std::swap(node.max[0], node.max[1]);
    }
  }

  void propagate(int node) {
    if(st[node].lazy > 0) {
      update_node(st[node], st[node].lazy);
      if(node < n) {
        st[2 * node].lazy += st[node].lazy;
        st[2 * node + 1].lazy += st[node].lazy;
      }
      st[node].lazy = 0;
    }
  }

  void pull(int node) {
    propagate(2 * node);
    propagate(2 * node + 1);
    st[node] = st[2 * node] + st[2 * node + 1];
  }

  void _update(int node, int pl, int pr, int l, int r, int val) {
    if(pl > pr || l > r) {
      return;
    }
    if(pl == l && pr == r) {
      st[node].lazy += val;
      return;
    }
    propagate(node);
    int mid = (pl + pr) / 2;
    _update(2 * node, pl, mid, l, std::min(r, mid), val);
    _update(2 * node + 1, mid + 1, pr, std::max(l, mid + 1), r, val);
    pull(node);
  }

  void update(int l, int r, int val) {
    _update(1, 0, n - 1, l, r, val);
  }

  MinMax _query(int node, int pl, int pr, int l, int r) {
    if(pl > pr || l > r) {
      return {INF_LL, -1};
    }
    if(pl == l && pr == r) {
      propagate(node);
      return {st[node].min[0], st[node].max[1]};
    }
    propagate(node);
    int mid = (pl + pr) / 2;
    return _query(2 * node, pl, mid, l, std::min(r, mid)) +
           _query(2 * node + 1, mid + 1, pr, std::max(l, mid + 1), r);
  }

  MinMax query(int l, int r) {
    return _query(1, 0, n - 1, l, r);
  }
};

int a[MAX_N];
SegTree st;

int main() {
  int n;
  std::cin >> n;
  for(int i = 0; i < n; i++) {
    std::cin >> a[i];
  }

  st.init(n, a);
  int q;
  std::cin >> q;
  for(int i = 0; i < q; i++) {
    int type, l, r;
    std::cin >> type >> l >> r;
    if(type == 0) {
      int val;
      std::cin >> val;
      st.update(l - 1, r - 1, val);
    } else {
      MinMax ans = st.query(l - 1, r - 1);
      std::cout << ((ans.min == INF_LL) ? -1 : ans.min) << " " << ans.max << "\n";
    }
  }

  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...