#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#define fi first
#define se second
using namespace std;
const int N = 2e5 + 10;
int a[N];
int x[N], t[N];
vector<pair<int, int>> st;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m; cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= m; i++) cin >> t[i] >> x[i];
int mx = 0;
// 对于数组a, [1, x[maxi]] 排序完之后,得再排序 [1, x[se-maxi]], 然后再排 [1, x[th-maxi]],以此类推。
// 会发现从前往后找,对于数组x, 要先遍历区间[1, m], 找到 max,再记录下 maxi,再将 mx 归 0。然后再遍历区间[maxi + 1, m],再找一个最大值 se-max,再把下标 se-maxi 记录下来,然后再遍历[se-maxi + 1, m], 一直不断遍历下去,有点像归并排序只处理右孩子区间一样,时间复杂度肯定超 O(N)了。
// 但从后往前找,对于数组x,mx 就不用归 0, 找的时候,先把 x[m]赋给 mx, (a[x[m]]在后续操作中会在最后一次排序操作中被单独排序),再把 x[m] 记录下来,往前遍历,如果x[i] <= mx, 说明在数组a中[1, x[i]]的元素排序操作会被 sort(a + 1, a + mx + 1) 或 sort(a + 1, a + mx + 1, greater<int>()) 覆盖掉;如果 x[i] > mx,说明在数组a中[1, x[i]]包括的元素要比[1, mx]还要多,记录下来,放到倒数第二次排序,继续往前遍历。只需遍历一遍,就把需要排序的区间给倒着存好了,时间复杂度为 O(N)。
for(int i = m; i >= 1; i--) {
if(mx < x[i]) {
st.push_back({t[i], x[i]});
mx = x[i];
}
}
for(int i = st.size() - 1; i >= 0; i--) {
int t = st[i].fi, x = st[i].se;
if(t == 1) sort(a + 1, a + x + 1);
else sort(a + 1, a + x + 1, greater<int>());
}
for(int i = 1; i <= n; i++) cout << a[i] << " ";
return 0;
}
// 附:x[maxi]为数组x在[1, m]范围内元素最大值,x[se-maxi]为数组x在[maxi + 1, m]元素最大值,x[th-maxi]为数组x在[se-maxi, m]元素最大值,以此类推。