smatskevich

Untitled

Aug 31st, 2025
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.15 KB | None | 0 0
  1. #include <algorithm>
  2. #include <array>
  3. #include <cassert>
  4. #include <climits>
  5. #include <cmath>
  6. #include <cstring>
  7. #include <iomanip>
  8. #include <iostream>
  9. #include <limits>
  10. #include <list>
  11. #include <map>
  12. #include <numeric>
  13. #include <queue>
  14. #include <random>
  15. #include <set>
  16. #include <sstream>
  17. #include <stack>
  18. #include <string>
  19. #include <tuple>
  20. #include <unordered_map>
  21. #include <unordered_set>
  22. #include <vector>
  23.  
  24. #define all(x) x.begin(), x.end()
  25. using namespace std;
  26. using ll = long long;
  27. using ld = long double;
  28. const double eps = 1e-10;
  29. const int mod = 1000000007;
  30.  
  31. vector<int> a;
  32. int left_border = 0, right_border = 0;
  33.  
  34. void LowerBounds(set<pair<int, int>>& points, set<pair<int, int>>& mins, set<pair<int, int>>& maxs, int add) {
  35.   int pos = points.begin()->first, cnt = points.begin()->second;
  36.   assert(cnt >= 1);
  37.   auto next = ++points.begin();
  38.   int nextpos = next->first, nextcnt = next->second;
  39.  
  40.   if (a[pos] > a[nextpos]) {
  41.     points.erase(points.begin());
  42.     if (cnt > 1) {
  43.       --cnt;
  44.       points.insert({pos, cnt});
  45.     } else {
  46.       left_border = nextpos;
  47.       if (mins.count({nextcnt, nextpos})) {
  48.         mins.erase({nextcnt, nextpos});
  49.         points.erase({nextpos, nextcnt});
  50.         nextcnt -= add;
  51.         points.insert({nextpos, nextcnt});
  52.       }
  53.     }
  54.   }
  55.   if (points.size() == 1) return;
  56.  
  57.   pos = points.rbegin()->first, cnt = points.rbegin()->second;
  58.   assert(cnt >= 1);
  59.   auto prev = ++points.rbegin();
  60.   int prevpos = prev->first, prevcnt = prev->second;
  61.  
  62.   if (a[pos] > a[prevpos]) {
  63.     points.erase(--points.end());
  64.     if (cnt > 1) {
  65.       --cnt;
  66.       points.insert({pos, cnt});
  67.     } else {
  68.       right_border = prevpos;
  69.       if (mins.count({prevcnt, prevpos})) {
  70.         mins.erase({prevcnt, prevpos});
  71.         points.erase({prevpos, prevcnt});
  72.         prevcnt -= add;
  73.         points.insert({prevpos, prevcnt});
  74.       }
  75.     }
  76.   }
  77. }
  78.  
  79. void UpperBounds(set<pair<int, int>>& points, set<pair<int, int>>& mins, set<pair<int, int>>& maxs, int add) {
  80.   int pos = points.begin()->first, cnt = points.begin()->second;
  81.   assert(cnt >= 1);
  82.   auto next = ++points.begin();
  83.   int nextpos = next->first, nextcnt = next->second;
  84.  
  85.   if (a[pos] < a[nextpos]) {
  86.     points.erase(points.begin());
  87.     if (cnt > 1) {
  88.       --cnt;
  89.       points.insert({pos, cnt});
  90.     } else {
  91.       left_border = nextpos;
  92.       if (maxs.count({nextcnt, nextpos})) {
  93.         maxs.erase({nextcnt, nextpos});
  94.         points.erase({nextpos, nextcnt});
  95.         nextcnt += add;
  96.         points.insert({nextpos, nextcnt});
  97.       }
  98.     }
  99.   }
  100.   if (points.size() == 1) return;
  101.  
  102.   pos = points.rbegin()->first, cnt = points.rbegin()->second;
  103.   assert(cnt >= 1);
  104.   auto prev = ++points.rbegin();
  105.   int prevpos = prev->first, prevcnt = prev->second;
  106.  
  107.   if (a[pos] < a[prevpos]) {
  108.     points.erase(--points.end());
  109.     if (cnt > 1) {
  110.       --cnt;
  111.       points.insert({pos, cnt});
  112.     } else {
  113.       right_border = prevpos;
  114.       if (maxs.count({prevcnt, prevpos})) {
  115.         maxs.erase({prevcnt, prevpos});
  116.         points.erase({prevpos, prevcnt});
  117.         prevcnt += add;
  118.         points.insert({prevpos, prevcnt});
  119.       }
  120.     }
  121.   }
  122. }
  123.  
  124. inline bool IsBorder(int pos) { return pos == left_border || pos == right_border; }
  125.  
  126. void UpdateLower(set<pair<int, int>>::iterator it1, set<pair<int, int>>::iterator it2,
  127.                  set<pair<int, int>>& mins, set<pair<int, int>>& maxs,
  128.                  set<pair<int, int>>& points, int add) {
  129.   assert(it1 != points.end());
  130.   assert(it2 != points.end());
  131.  
  132.   int pos1 = it1->first, cnt1 = it1->second;
  133.   int pos2 = it2->first, cnt2 = it2->second;
  134.   auto min1 = mins.find({cnt1, pos1});
  135.   auto min2 = mins.find({cnt2, pos2});
  136.   if (min1 == mins.end() && min2 == mins.end()) {
  137.     if (a[pos1] == a[pos2]) {
  138.       points.erase(it1);
  139.       points.erase(it2);
  140.       if (IsBorder(pos1) || IsBorder(pos2)) {
  141.         int cnt = cnt1 + cnt2;
  142.         int pos = IsBorder(pos1) ? pos1 : pos2;
  143.         points.insert({pos, cnt});
  144.       } else {
  145.         cnt1 += cnt2 - add;
  146.         points.insert({pos1, cnt1});
  147.         maxs.insert({cnt1, pos1});
  148.       }
  149.     } else {
  150.       if (a[pos1] < a[pos2]) { swap(pos1, pos2); swap(cnt1, cnt2); swap(it1, it2); }
  151.       if (!IsBorder(pos1)) {
  152.         points.erase(it1);
  153.         cnt1 -= add;
  154.         points.insert({pos1, cnt1});
  155.         maxs.insert({cnt1, pos1});
  156.       }
  157.     }
  158.     return;
  159.   }
  160.   if (min1 == mins.end()) { swap(min1, min2); swap(it1, it2); swap(cnt1, cnt2); swap(pos1, pos2); }
  161.   if (min2 == mins.end()) {
  162.     if (a[pos1] == a[pos2]) {
  163.       mins.erase(min1);
  164.       points.erase(it1);
  165.       points.erase(it2);
  166.       cnt2 += cnt1 - add;
  167.       points.insert({pos2, cnt2});
  168.     } else if (a[pos1] < a[pos2]) {
  169.       if (!IsBorder(pos2)) {
  170.         points.erase(it2);
  171.         cnt2 -= add;
  172.         points.insert({pos2, cnt2});
  173.         maxs.insert({cnt2, pos2});
  174.       }
  175.     } else {
  176.       mins.erase(min1);
  177.       points.erase(it1);
  178.       cnt1 -= add;
  179.       points.insert({pos1, cnt1});
  180.     }
  181.     return;
  182.   }
  183.   if (a[pos1] == a[pos2]) {
  184.     mins.erase(min1);
  185.     mins.erase(min2);
  186.     points.erase(it1);
  187.     points.erase(it2);
  188.     cnt1 += cnt2 - add;
  189.     points.insert({pos1, cnt1});
  190.     mins.insert({cnt1, pos1});
  191.   } else {
  192.     if (a[pos1] > a[pos2]) { swap(pos1, pos2); swap(cnt1, cnt2); swap(it1, it2); swap(min1, min2); }
  193.     mins.erase(min2);
  194.     points.erase(it2);
  195.     cnt2 -= add;
  196.     points.insert({pos2, cnt2});
  197.   }
  198. }
  199.  
  200. void UpdateUpper(set<pair<int, int>>::iterator it1, set<pair<int, int>>::iterator it2,
  201.                  set<pair<int, int>>& mins, set<pair<int, int>>& maxs,
  202.                  set<pair<int, int>>& points, int add) {
  203.   assert(it1 != points.end());
  204.   assert(it2 != points.end());
  205.  
  206.   int pos1 = it1->first, cnt1 = it1->second;
  207.   int pos2 = it2->first, cnt2 = it2->second;
  208.   auto max1 = maxs.find({cnt1, pos1});
  209.   auto max2 = maxs.find({cnt2, pos2});
  210.   if (max1 == maxs.end() && max2 == maxs.end()) {
  211.     if (a[pos1] == a[pos2]) {
  212.       points.erase(it1);
  213.       points.erase(it2);
  214.       if (IsBorder(pos1) || IsBorder(pos2)) {
  215.         int cnt = cnt1 + cnt2;
  216.         int pos = IsBorder(pos1) ? pos1 : pos2;
  217.         points.insert({pos, cnt});
  218.       } else {
  219.         cnt1 += cnt2 + add;
  220.         points.insert({pos1, cnt1});
  221.         mins.insert({cnt1, pos1});
  222.       }
  223.     } else {
  224.       if (a[pos1] > a[pos2]) { swap(pos1, pos2); swap(cnt1, cnt2); swap(it1, it2); }
  225.       if (!IsBorder(pos1)) {
  226.         points.erase(it1);
  227.         cnt1 += add;
  228.         points.insert({pos1, cnt1});
  229.         mins.insert({cnt1, pos1});
  230.       }
  231.     }
  232.     return;
  233.   }
  234.   if (max1 == maxs.end()) { swap(max1, max2); swap(it1, it2); swap(cnt1, cnt2); swap(pos1, pos2); }
  235.   if (max2 == maxs.end()) {
  236.     if (a[pos1] == a[pos2]) {
  237.       maxs.erase(max1);
  238.       points.erase(it1);
  239.       points.erase(it2);
  240.       cnt2 += cnt1 + add;
  241.       points.insert({pos2, cnt2});
  242.     } else if (a[pos1] > a[pos2]) {
  243.       if (!IsBorder(pos2)) {
  244.         points.erase(it2);
  245.         cnt2 += add;
  246.         points.insert({pos2, cnt2});
  247.         mins.insert({cnt2, pos2});
  248.       }
  249.     } else {
  250.       maxs.erase(max1);
  251.       points.erase(it1);
  252.       cnt1 += add;
  253.       points.insert({pos1, cnt1});
  254.     }
  255.     return;
  256.   }
  257.   if (a[pos1] == a[pos2]) {
  258.     maxs.erase(max1);
  259.     maxs.erase(max2);
  260.     points.erase(it1);
  261.     points.erase(it2);
  262.     cnt1 += cnt2 + add;
  263.     points.insert({pos1, cnt1});
  264.     maxs.insert({cnt1, pos1});
  265.   } else {
  266.     if (a[pos1] < a[pos2]) { swap(pos1, pos2); swap(cnt1, cnt2); swap(it1, it2); swap(max1, max2); }
  267.     maxs.erase(max2);
  268.     points.erase(it2);
  269.     cnt2 += add;
  270.     points.insert({pos2, cnt2});
  271.   }
  272. }
  273.  
  274. void Solve() {
  275.   int n; cin >> n;
  276.   a.resize(n);
  277.   for (int i = 0; i < n; ++i) cin >> a[i];
  278.   string s; cin >> s;
  279.   set<pair<int, int>> points;  // Различные точки в исходном порядке с кратностями {pos, count}
  280.   set<pair<int, int>> mins, maxs;  // Отдельно минимумы и максимумы {count, pos}
  281.   int add = 0;
  282.   // Готовим массивы points, mins, maxs к проходу
  283.   for (int i = 0; i < n;) {
  284.     int pos = i;
  285.     right_border = pos;
  286.     int val = a[pos], cnt = 1;
  287.     for (++i; i < n && a[i] == val; ++i, ++cnt);
  288.     if (points.empty() || i == n) {
  289.       points.insert({pos, cnt});
  290.       continue;
  291.     }
  292.     int prev = a[points.rbegin()->first];
  293.     assert(prev != val);
  294.     assert(a[i] != val);
  295.     if (prev > val && a[i] > val) mins.insert({cnt, pos});
  296.     if (prev < val && a[i] < val) maxs.insert({cnt, pos});
  297.     points.insert({pos, cnt});
  298.   }
  299.   for (int i = 0; i < n - 1 && points.size() > 1; ++i) {
  300.     bool lower = s[i] == 'm';
  301.     add += lower ? -1 : 1;
  302.     if (lower) {
  303.       // Срезаем краешки
  304.       LowerBounds(points, mins, maxs, add);
  305.       // Срезаем максимумы
  306.       while (!maxs.empty() && maxs.begin()->first + add == 0) {
  307.         int cnt = maxs.begin()->first, pos = maxs.begin()->second;
  308.         maxs.erase(maxs.begin());
  309.         auto it = points.find({pos, cnt});
  310.         assert(it != points.end());
  311.         points.erase(it);
  312.         auto next = points.lower_bound({pos, 0});
  313.         auto prev = next;
  314.         if (prev == points.begin()) prev = points.end();
  315.         else --prev;
  316.         UpdateLower(next, prev, mins, maxs, points, add);
  317.       }
  318.     } else {
  319.       // Срезаем краешки
  320.       UpperBounds(points, mins, maxs, add);
  321.       // Срезаем минимумы
  322.       while (!mins.empty() && mins.begin()->first - add == 0) {
  323.         int cnt = mins.begin()->first, pos = mins.begin()->second;
  324.         mins.erase(mins.begin());
  325.         auto it = points.find({pos, cnt});
  326.         assert(it != points.end());
  327.         points.erase(it);
  328.         auto next = points.lower_bound({pos, 0});
  329.         auto prev = next;
  330.         if (prev == points.begin()) prev = points.end();
  331.         else --prev;
  332.         UpdateUpper(next, prev, mins, maxs, points, add);
  333.       }
  334.     }
  335.   }
  336.   cout << a[points.begin()->first] << "\n";
  337. }
  338.  
  339. int main() {
  340.   ios::sync_with_stdio(false);
  341.   cin.tie(nullptr);
  342.   cout.tie(nullptr);
  343.  
  344.   Solve();
  345.   return 0;
  346. }
  347.  
Advertisement
Add Comment
Please, Sign In to add comment