Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vector>
- #include <iostream>
- #include <cassert>
- #include <climits>
- // 13 = 8 + 4 + 1 0:00001101 1:00000110 2:00000011 3:00000001 4:00000000
- int next_2_degree(int value)
- {
- int i = 0;
- while(value >> i) ++i;
- return 1 << i;
- }
- //-----------------------------------------------------------------------------
- class MinSegmentTree {
- public:
- MinSegmentTree(const std::vector<int>& arr, int defaultValue);
- int GetMin(int left, int right) const;
- void Update(int val, int pos);
- private:
- std::vector<int> min_;
- int default_;
- void build(int index, int left, int right);
- void update(int index, int left, int right, int val, int pos);
- int getMin(int index, int i_left, int i_right, int left, int right) const;
- };
- MinSegmentTree::MinSegmentTree(const std::vector<int>& arr, int defaultValue)
- : min_(next_2_degree(arr.size()) * 2, defaultValue),
- default_(defaultValue) {
- // Предзаполняем последний слой дерева отрезков
- std::copy(arr.begin(), arr.end(), min_.begin() + min_.size() / 2 - 1);
- build(0, 0, min_.size() / 2 - 1);
- }
- void MinSegmentTree::build(int index, int left, int right) {
- if (left == right) return;
- const int mid = (left + right) >> 1;
- build(2 * index + 1, left, mid);
- build(2 * index + 2, mid + 1, right);
- min_[index] = std::min(min_[2 * index + 1], min_[2 * index + 2]);
- }
- void MinSegmentTree::Update(int val, int pos) {
- update(0, 0, min_.size() / 2 - 1, val, pos);
- return;
- }
- void MinSegmentTree::update(int index, int left, int right, int val, int pos) {
- if (left == right) {
- min_[index] = val;
- return;
- }
- const int mid = (left + right) >> 1;
- if (pos <= mid) {
- update(2 * index + 1, left, mid, val, pos);
- }
- if (pos > mid) {
- update(2 * index + 2, mid + 1, right, val, pos);
- }
- min_[index] = std::min(min_[2 * index + 1], min_[2 * index + 2]);
- }
- int MinSegmentTree::GetMin(int left, int right) const {
- return getMin(0, 0, min_.size() / 2 - 1, left, right);
- }
- int MinSegmentTree::getMin(int index, int i_left, int i_right, int left, int right) const {
- assert(i_left <= i_right && left <= right);
- // Пересечения нет. Отрезок левее
- if (right < i_left) { return default_; }
- // Пересечения нет. Отрезок правее
- if (i_right < left) { return default_; }
- if (left <= i_left && i_right <= right) {
- return min_[index];
- }
- const int mid = (i_left + i_right) / 2;
- return std::min(getMin(2 * index + 1, i_left, mid, left, right),
- getMin(2 * index + 2, mid + 1, i_right, left, right));
- }
- //-----------------------------------------------------------------------------
- class MaxSegmentTree {
- public:
- MaxSegmentTree(const std::vector<int>& arr, int defaultValue);
- int GetMax(int left, int right) const;
- void Update(int val, int pos);
- private:
- std::vector <int> max_;
- int default_;
- void build(int index, int left, int right);
- void update(int index, int left, int right, int val, int pos);
- int getMax(int index, int i_left, int i_right, int left, int right) const;
- };
- MaxSegmentTree::MaxSegmentTree (const std::vector<int>& arr, int defaultValue)
- : max_(next_2_degree(arr.size()) * 2, defaultValue),
- default_(defaultValue) {
- std::copy(arr.begin(), arr.end(), max_.begin() + max_.size() / 2 - 1);
- build(0, 0, max_.size() / 2 - 1);
- }
- void MaxSegmentTree::build(int index, int left, int right) {
- if (left == right) return;
- const int mid = (left + right) >> 1;
- build(2 * index + 1, left, mid);
- build(2 * index + 2, mid + 1, right);
- max_[index] = std::max(max_[2 * index + 1], max_[2 * index + 2]);
- }
- void MaxSegmentTree::Update(int val, int pos) {
- update(0, 0, max_.size() / 2 - 1, val, pos);
- return;
- }
- void MaxSegmentTree::update(int index, int left, int right, int val, int pos) {
- if (left == right) {
- max_[index] = val;
- return;
- }
- const int mid = (left + right) >> 1;
- if (pos <= mid) {
- update(2 * index + 1, left, mid, val, pos);
- }
- if (pos > mid) {
- update(2 * index + 2, mid + 1, right, val, pos);
- }
- max_[index] = std::max(max_[2 * index + 1], max_[2 * index + 2]);
- }
- int MaxSegmentTree::GetMax(int left, int right) const {
- return getMax(0, 0, max_.size() / 2 - 1, left, right);
- }
- int MaxSegmentTree::getMax(int index, int i_left, int i_right, int left, int right) const {
- assert(i_left <= i_right && left <= right);
- if (right < i_left) { return default_; }
- if (left > i_right) { return default_; }
- if (left <= i_left && i_right <= right) {
- return max_[index];
- }
- const int mid = (i_left + i_right) / 2;
- return std::max(getMax(2 * index + 1, i_left, mid, left, right),
- getMax(2 * index + 2, mid + 1, i_right, left, right));
- }
- //-----------------------------------------------------------------------------
- int main() {
- int n = 100000;
- std::vector<int> arr(n, 0);
- for (int i = 1; i <= n; ++i) {
- int fst = (i % 12345 * i % 12345) % 12345,
- snd = (i % 23456 * i % 23456 * i % 23456) % 23456;
- arr[i - 1] = fst + snd;
- }
- MinSegmentTree minTree(arr, INT_MAX);
- MaxSegmentTree maxTree(arr, INT_MIN);
- int k;
- std::cin >> k;
- for (int i = 0; i < k; ++i) {
- int x, y;
- std::cin >> x >> y;
- if (x > 0) {
- --x;
- --y;
- std::cout << maxTree.GetMax(x, y) - minTree.GetMin(x, y) << '\n';
- } else {
- x *= -1;
- --x;
- maxTree.Update(y, x);
- minTree.Update(y, x);
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement