1
0

HYSBZ-4552.cpp 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. #include <iostream>
  2. #include <map>
  3. #include <vector>
  4. using namespace std;
  5. struct Node { int left = 0, right = 0, count = 0; };
  6. struct Block { int right, root; bool descending; };
  7. int main() {
  8. ios::sync_with_stdio(false); cin.tie(nullptr);
  9. int n, operations; cin >> n >> operations;
  10. vector<Node> tree(1); tree.reserve(static_cast<size_t>(n + 2 * operations) * 22);
  11. auto new_node = [&] { tree.push_back({}); return static_cast<int>(tree.size()) - 1; };
  12. auto insert = [&](auto &&self, int u, int l, int r, int p) -> int {
  13. if (!u) u = new_node(); ++tree[u].count;
  14. if (l < r) { int mid = (l + r) / 2; if (p <= mid) tree[u].left = self(self, tree[u].left, l, mid, p); else tree[u].right = self(self, tree[u].right, mid + 1, r, p); }
  15. return u;
  16. };
  17. auto pull = [&](int u) { tree[u].count = tree[tree[u].left].count + tree[tree[u].right].count; };
  18. auto split_small = [&](auto &&self, int u, int k, int l, int r) -> pair<int,int> {
  19. if (!u) return {0, 0};
  20. if (k == 0) return {0, u};
  21. if (k == tree[u].count) return {u, 0};
  22. int a = new_node(), b = new_node(), mid = (l + r) / 2;
  23. int left_count = tree[tree[u].left].count;
  24. if (k <= left_count) {
  25. auto [x, y] = self(self, tree[u].left, k, l, mid);
  26. tree[a].left = x; tree[b].left = y; tree[b].right = tree[u].right;
  27. } else {
  28. auto [x, y] = self(self, tree[u].right, k - left_count, mid + 1, r);
  29. tree[a].left = tree[u].left; tree[a].right = x; tree[b].right = y;
  30. }
  31. pull(a); pull(b); return {a, b};
  32. };
  33. auto merge = [&](auto &&self, int a, int b, int l, int r) -> int {
  34. if (!a) return b; if (!b) return a;
  35. if (l < r) { int mid = (l + r) / 2; tree[a].left = self(self, tree[a].left, tree[b].left, l, mid); tree[a].right = self(self, tree[a].right, tree[b].right, mid + 1, r); }
  36. tree[a].count += tree[b].count; return a;
  37. };
  38. auto kth = [&](auto &&self, int u, int l, int r, int k) -> int {
  39. if (l == r) return l; int mid = (l + r) / 2, left_count = tree[tree[u].left].count;
  40. return k <= left_count ? self(self, tree[u].left, l, mid, k) : self(self, tree[u].right, mid + 1, r, k - left_count);
  41. };
  42. map<int, Block> blocks;
  43. for (int i = 1, value; i <= n; ++i) { cin >> value; blocks[i] = {i, insert(insert, 0, 1, n, value), false}; }
  44. auto split_position = [&](int position) {
  45. if (position > n) return blocks.end();
  46. auto it = prev(blocks.upper_bound(position));
  47. if (it->first == position) return it;
  48. int l = it->first, r = it->second.right, take = position - l, total = r - l + 1;
  49. int first, second;
  50. if (!it->second.descending) tie(first, second) = split_small(split_small, it->second.root, take, 1, n);
  51. else tie(second, first) = split_small(split_small, it->second.root, total - take, 1, n);
  52. bool direction = it->second.descending; it->second = {position - 1, first, direction};
  53. return blocks.emplace(position, Block{r, second, direction}).first;
  54. };
  55. while (operations--) {
  56. int op, l, r; cin >> op >> l >> r;
  57. auto finish = split_position(r + 1), begin = split_position(l);
  58. int root = 0;
  59. for (auto it = begin; it != finish; ++it) root = merge(merge, root, it->second.root, 1, n);
  60. blocks.erase(begin, finish); blocks[l] = {r, root, op == 1};
  61. }
  62. int q; cin >> q; auto it = prev(blocks.upper_bound(q));
  63. int offset = q - it->first, size = it->second.right - it->first + 1;
  64. cout << kth(kth, it->second.root, 1, n, it->second.descending ? size - offset : offset + 1) << '\n';
  65. }