Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <algorithm>
- using std::cout;
- using std::endl;
- using std::vector;
- using ld = long double;
- /** @brief range update, range query segtree */
- template <typename T>
- class RURQSegtree {
- private:
- const T NO_OP = -INT32_MIN;
- int len;
- vector<T> vals;
- vector<T> ops;
- T calc_op(T a, T b) {
- return a + b;
- }
- void mod_val(T& a, T b, T len) {
- a = b == NO_OP ? a : b * len;
- }
- void propagate(int at, int left, int right) {
- if (right - left == 1) {
- return;
- }
- int mid = (left + right) / 2;
- mod_val(vals[2 * at + 1], ops[at], mid - left);
- mod_val(ops[2 * at + 1], ops[at], 1);
- mod_val(vals[2 * at + 2], ops[at], right - mid);
- mod_val(ops[2 * at + 2], ops[at], 1);
- ops[at] = NO_OP;
- }
- void set_range(int start, int end, T val, int at, int left, int right) {
- propagate(at, left, right);
- if (left >= end || start >= right) {
- return;
- }
- if (start <= left && right <= end) {
- mod_val(vals[at], val, right - left);
- mod_val(ops[at], val, 1);
- return;
- }
- int mid = (left + right) / 2;
- set_range(start, end, val, 2 * at + 1, left, mid);
- set_range(start, end, val, 2 * at + 2, mid, right);
- vals[at] = calc_op(vals[2 * at + 1], vals[2 * at + 2]);
- mod_val(vals[at], ops[at], right - left);
- }
- T sum_range(int start, int end, int at, int left, int right) {
- propagate(at, left, right);
- if (left >= end || start >= right) {
- return 0;
- }
- if (start <= left && right <= end) {
- return vals[at];
- }
- int mid = (left + right) / 2;
- T left_res = sum_range(start, end, 2 * at + 1, left, mid);
- T right_res = sum_range(start, end, 2 * at + 2, mid, right);
- T ret = calc_op(left_res, right_res);
- mod_val(ret, ops[at], std::min(end, right) - std::max(start, left));
- return ret;
- }
- public:
- RURQSegtree(int len) {
- int actual_len = 1;
- while (actual_len < len) {
- actual_len *= 2;
- }
- this->len = actual_len;
- vals = vector<T>(2 * actual_len);
- ops = vector<T>(2 * actual_len);
- }
- /** @brief sets all elements in [start, end) to val */
- void set_range(int start, int end, T val) {
- set_range(start, end, val, 0, 0, len);
- }
- /** @return the sum of all values in the range [start, end) */
- T sum_range(int start, int end) {
- return sum_range(start, end, 0, 0, len);
- }
- };
- /**
- * 2022 dec gold
- * 5
- * 2 4 3 1 5
- * 3
- * 4 3
- * 1 3
- * 3 2 should output 7, 10, and 7, each on a new line
- */
- int main() {
- std::ios::sync_with_stdio(false);
- std::cin.tie(NULL);
- int mountain_num;
- std::cin >> mountain_num;
- vector<int> heights(mountain_num);
- for (int& m : heights) {
- std::cin >> m;
- }
- vector<RURQSegtree<ld>> mtns1;
- vector<RURQSegtree<int>> mtns2;
- long long viewable_pairs = 0;
- for (int m = 0; m < mountain_num; m++) {
- mtns1.push_back(RURQSegtree<ld>(mountain_num));
- mtns2.push_back(RURQSegtree<int>(mountain_num));
- ld curr_max = INT64_MIN;
- int last = 0;
- for (int other = m + 1; other < mountain_num; other++) {
- ld slope = (ld) (heights[other] - heights[m]) / (other - m);
- if (slope >= curr_max) {
- mtns1[m].set_range(last, other, curr_max);
- mtns2[m].set_range(other, other + 1, 1);
- curr_max = slope;
- viewable_pairs++;
- last = other;
- }
- }
- mtns1[m].set_range(last, mountain_num, curr_max);
- }
- cout << "done" << endl;
- int query_num;
- std::cin >> query_num;
- for (int q = 0; q < query_num; q++) {
- int pos, inc;
- std::cin >> pos >> inc;
- pos--;
- heights[pos] += inc;
- for (int m = 0; m < pos; m++) {
- ld slope = (ld) (heights[pos] - heights[m]) / (pos - m);
- if (slope < mtns1[m].sum_range(pos, pos + 1)) {
- continue;
- }
- int lo = pos;
- int hi = mountain_num;
- while (lo <= hi) {
- int mid = (lo + hi) / 2;
- float cmp_slope = mtns1[m].sum_range(mid, mid + 1);
- if (cmp_slope > slope) {
- hi = mid - 1;
- } else if (cmp_slope == slope) {
- if (mid < pos) {
- lo = mid + 1;
- } else {
- hi = mid - 1;
- }
- } else {
- lo = mid + 1;
- }
- }
- mtns1[m].set_range(pos, lo, slope);
- viewable_pairs -= mtns2[m].sum_range(pos, lo) - 1;
- mtns2[m].set_range(pos, lo, 0);
- mtns2[m].set_range(pos, pos + 1, 1);
- }
- ld curr_max = INT64_MIN;
- viewable_pairs -= mtns2[pos].sum_range(0, mountain_num);
- int last = 0;
- for (int m = pos + 1; m < mountain_num; m++) {
- ld slope = (ld) (heights[m] - heights[pos]) / (m - pos);
- if (slope >= curr_max) {
- mtns1[pos].set_range(last, m, curr_max);
- mtns2[pos].set_range(m, m + 1, 1);
- curr_max = slope;
- last = m;
- }
- }
- mtns1[pos].set_range(last, mountain_num, curr_max);
- viewable_pairs += mtns2[pos].sum_range(0, mountain_num);
- cout << viewable_pairs << '\n';
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement