Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <array>
- #include <cassert>
- #include <climits>
- #include <cmath>
- #include <cstring>
- #include <iomanip>
- #include <iostream>
- #include <limits>
- #include <list>
- #include <map>
- #include <numeric>
- #include <queue>
- #include <random>
- #include <set>
- #include <sstream>
- #include <stack>
- #include <string>
- #include <tuple>
- #include <unordered_map>
- #include <unordered_set>
- #include <vector>
- #define all(x) x.begin(), x.end()
- using namespace std;
- using ll = long long;
- using ld = long double;
- const double eps = 1e-10;
- const int mod = 1000000007;
- vector<int> a;
- int left_border = 0, right_border = 0;
- void LowerBounds(set<pair<int, int>>& points, set<pair<int, int>>& mins, set<pair<int, int>>& maxs, int add) {
- int pos = points.begin()->first, cnt = points.begin()->second;
- assert(cnt >= 1);
- auto next = ++points.begin();
- int nextpos = next->first, nextcnt = next->second;
- if (a[pos] > a[nextpos]) {
- points.erase(points.begin());
- if (cnt > 1) {
- --cnt;
- points.insert({pos, cnt});
- } else {
- left_border = nextpos;
- if (mins.count({nextcnt, nextpos})) {
- mins.erase({nextcnt, nextpos});
- points.erase({nextpos, nextcnt});
- nextcnt -= add;
- points.insert({nextpos, nextcnt});
- }
- }
- }
- if (points.size() == 1) return;
- pos = points.rbegin()->first, cnt = points.rbegin()->second;
- assert(cnt >= 1);
- auto prev = ++points.rbegin();
- int prevpos = prev->first, prevcnt = prev->second;
- if (a[pos] > a[prevpos]) {
- points.erase(--points.end());
- if (cnt > 1) {
- --cnt;
- points.insert({pos, cnt});
- } else {
- right_border = prevpos;
- if (mins.count({prevcnt, prevpos})) {
- mins.erase({prevcnt, prevpos});
- points.erase({prevpos, prevcnt});
- prevcnt -= add;
- points.insert({prevpos, prevcnt});
- }
- }
- }
- }
- void UpperBounds(set<pair<int, int>>& points, set<pair<int, int>>& mins, set<pair<int, int>>& maxs, int add) {
- int pos = points.begin()->first, cnt = points.begin()->second;
- assert(cnt >= 1);
- auto next = ++points.begin();
- int nextpos = next->first, nextcnt = next->second;
- if (a[pos] < a[nextpos]) {
- points.erase(points.begin());
- if (cnt > 1) {
- --cnt;
- points.insert({pos, cnt});
- } else {
- left_border = nextpos;
- if (maxs.count({nextcnt, nextpos})) {
- maxs.erase({nextcnt, nextpos});
- points.erase({nextpos, nextcnt});
- nextcnt += add;
- points.insert({nextpos, nextcnt});
- }
- }
- }
- if (points.size() == 1) return;
- pos = points.rbegin()->first, cnt = points.rbegin()->second;
- assert(cnt >= 1);
- auto prev = ++points.rbegin();
- int prevpos = prev->first, prevcnt = prev->second;
- if (a[pos] < a[prevpos]) {
- points.erase(--points.end());
- if (cnt > 1) {
- --cnt;
- points.insert({pos, cnt});
- } else {
- right_border = prevpos;
- if (maxs.count({prevcnt, prevpos})) {
- maxs.erase({prevcnt, prevpos});
- points.erase({prevpos, prevcnt});
- prevcnt += add;
- points.insert({prevpos, prevcnt});
- }
- }
- }
- }
- inline bool IsBorder(int pos) { return pos == left_border || pos == right_border; }
- void UpdateLower(set<pair<int, int>>::iterator it1, set<pair<int, int>>::iterator it2,
- set<pair<int, int>>& mins, set<pair<int, int>>& maxs,
- set<pair<int, int>>& points, int add) {
- assert(it1 != points.end());
- assert(it2 != points.end());
- int pos1 = it1->first, cnt1 = it1->second;
- int pos2 = it2->first, cnt2 = it2->second;
- auto min1 = mins.find({cnt1, pos1});
- auto min2 = mins.find({cnt2, pos2});
- if (min1 == mins.end() && min2 == mins.end()) {
- if (a[pos1] == a[pos2]) {
- points.erase(it1);
- points.erase(it2);
- if (IsBorder(pos1) || IsBorder(pos2)) {
- int cnt = cnt1 + cnt2;
- int pos = IsBorder(pos1) ? pos1 : pos2;
- points.insert({pos, cnt});
- } else {
- cnt1 += cnt2 - add;
- points.insert({pos1, cnt1});
- maxs.insert({cnt1, pos1});
- }
- } else {
- if (a[pos1] < a[pos2]) { swap(pos1, pos2); swap(cnt1, cnt2); swap(it1, it2); }
- if (!IsBorder(pos1)) {
- points.erase(it1);
- cnt1 -= add;
- points.insert({pos1, cnt1});
- maxs.insert({cnt1, pos1});
- }
- }
- return;
- }
- if (min1 == mins.end()) { swap(min1, min2); swap(it1, it2); swap(cnt1, cnt2); swap(pos1, pos2); }
- if (min2 == mins.end()) {
- if (a[pos1] == a[pos2]) {
- mins.erase(min1);
- points.erase(it1);
- points.erase(it2);
- cnt2 += cnt1 - add;
- points.insert({pos2, cnt2});
- } else if (a[pos1] < a[pos2]) {
- if (!IsBorder(pos2)) {
- points.erase(it2);
- cnt2 -= add;
- points.insert({pos2, cnt2});
- maxs.insert({cnt2, pos2});
- }
- } else {
- mins.erase(min1);
- points.erase(it1);
- cnt1 -= add;
- points.insert({pos1, cnt1});
- }
- return;
- }
- if (a[pos1] == a[pos2]) {
- mins.erase(min1);
- mins.erase(min2);
- points.erase(it1);
- points.erase(it2);
- cnt1 += cnt2 - add;
- points.insert({pos1, cnt1});
- mins.insert({cnt1, pos1});
- } else {
- if (a[pos1] > a[pos2]) { swap(pos1, pos2); swap(cnt1, cnt2); swap(it1, it2); swap(min1, min2); }
- mins.erase(min2);
- points.erase(it2);
- cnt2 -= add;
- points.insert({pos2, cnt2});
- }
- }
- void UpdateUpper(set<pair<int, int>>::iterator it1, set<pair<int, int>>::iterator it2,
- set<pair<int, int>>& mins, set<pair<int, int>>& maxs,
- set<pair<int, int>>& points, int add) {
- assert(it1 != points.end());
- assert(it2 != points.end());
- int pos1 = it1->first, cnt1 = it1->second;
- int pos2 = it2->first, cnt2 = it2->second;
- auto max1 = maxs.find({cnt1, pos1});
- auto max2 = maxs.find({cnt2, pos2});
- if (max1 == maxs.end() && max2 == maxs.end()) {
- if (a[pos1] == a[pos2]) {
- points.erase(it1);
- points.erase(it2);
- if (IsBorder(pos1) || IsBorder(pos2)) {
- int cnt = cnt1 + cnt2;
- int pos = IsBorder(pos1) ? pos1 : pos2;
- points.insert({pos, cnt});
- } else {
- cnt1 += cnt2 + add;
- points.insert({pos1, cnt1});
- mins.insert({cnt1, pos1});
- }
- } else {
- if (a[pos1] > a[pos2]) { swap(pos1, pos2); swap(cnt1, cnt2); swap(it1, it2); }
- if (!IsBorder(pos1)) {
- points.erase(it1);
- cnt1 += add;
- points.insert({pos1, cnt1});
- mins.insert({cnt1, pos1});
- }
- }
- return;
- }
- if (max1 == maxs.end()) { swap(max1, max2); swap(it1, it2); swap(cnt1, cnt2); swap(pos1, pos2); }
- if (max2 == maxs.end()) {
- if (a[pos1] == a[pos2]) {
- maxs.erase(max1);
- points.erase(it1);
- points.erase(it2);
- cnt2 += cnt1 + add;
- points.insert({pos2, cnt2});
- } else if (a[pos1] > a[pos2]) {
- if (!IsBorder(pos2)) {
- points.erase(it2);
- cnt2 += add;
- points.insert({pos2, cnt2});
- mins.insert({cnt2, pos2});
- }
- } else {
- maxs.erase(max1);
- points.erase(it1);
- cnt1 += add;
- points.insert({pos1, cnt1});
- }
- return;
- }
- if (a[pos1] == a[pos2]) {
- maxs.erase(max1);
- maxs.erase(max2);
- points.erase(it1);
- points.erase(it2);
- cnt1 += cnt2 + add;
- points.insert({pos1, cnt1});
- maxs.insert({cnt1, pos1});
- } else {
- if (a[pos1] < a[pos2]) { swap(pos1, pos2); swap(cnt1, cnt2); swap(it1, it2); swap(max1, max2); }
- maxs.erase(max2);
- points.erase(it2);
- cnt2 += add;
- points.insert({pos2, cnt2});
- }
- }
- void Solve() {
- int n; cin >> n;
- a.resize(n);
- for (int i = 0; i < n; ++i) cin >> a[i];
- string s; cin >> s;
- set<pair<int, int>> points; // Различные точки в исходном порядке с кратностями {pos, count}
- set<pair<int, int>> mins, maxs; // Отдельно минимумы и максимумы {count, pos}
- int add = 0;
- // Готовим массивы points, mins, maxs к проходу
- for (int i = 0; i < n;) {
- int pos = i;
- right_border = pos;
- int val = a[pos], cnt = 1;
- for (++i; i < n && a[i] == val; ++i, ++cnt);
- if (points.empty() || i == n) {
- points.insert({pos, cnt});
- continue;
- }
- int prev = a[points.rbegin()->first];
- assert(prev != val);
- assert(a[i] != val);
- if (prev > val && a[i] > val) mins.insert({cnt, pos});
- if (prev < val && a[i] < val) maxs.insert({cnt, pos});
- points.insert({pos, cnt});
- }
- for (int i = 0; i < n - 1 && points.size() > 1; ++i) {
- bool lower = s[i] == 'm';
- add += lower ? -1 : 1;
- if (lower) {
- // Срезаем краешки
- LowerBounds(points, mins, maxs, add);
- // Срезаем максимумы
- while (!maxs.empty() && maxs.begin()->first + add == 0) {
- int cnt = maxs.begin()->first, pos = maxs.begin()->second;
- maxs.erase(maxs.begin());
- auto it = points.find({pos, cnt});
- assert(it != points.end());
- points.erase(it);
- auto next = points.lower_bound({pos, 0});
- auto prev = next;
- if (prev == points.begin()) prev = points.end();
- else --prev;
- UpdateLower(next, prev, mins, maxs, points, add);
- }
- } else {
- // Срезаем краешки
- UpperBounds(points, mins, maxs, add);
- // Срезаем минимумы
- while (!mins.empty() && mins.begin()->first - add == 0) {
- int cnt = mins.begin()->first, pos = mins.begin()->second;
- mins.erase(mins.begin());
- auto it = points.find({pos, cnt});
- assert(it != points.end());
- points.erase(it);
- auto next = points.lower_bound({pos, 0});
- auto prev = next;
- if (prev == points.begin()) prev = points.end();
- else --prev;
- UpdateUpper(next, prev, mins, maxs, points, add);
- }
- }
- }
- cout << a[points.begin()->first] << "\n";
- }
- int main() {
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- Solve();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment