CodeForces-631C Report 單調棧,思維
阿新 • • 發佈:2020-10-09
CodeForces-631C Report 單調棧,思維
題意
給定一個初始序列\(a\)
輸出經過\(m\)次操作後的序列
每個操作是兩種之一
- \(1 \quad r\) ,將序列\([1,r]\) 從小到大排序
- \(2\quad r\) ,將序列\([1,r]\)從大到小排序
分析
暴力顯然是不可取的。
注意到性質
對於操作\(i,j\),若$i > j \(且\)r_i > r_j$ 那麼這個\(j\)是無效的。
這提示我們利用這個性質縮小範圍。
根據\(r\)維護一個單調遞減的單調棧。每次我們只需要考慮兩個相鄰的棧的\(r\)之間的元素。
並且由於之前最大的\(r\)
這樣就可以\(O(nlogn)\)實現,瓶頸在於排序。
程式碼
int a[200005]; int b[200005]; int c[200005]; int op[200005]; int st[200005]; int main() { int n = readint(); int m = readint(); int ptr = 0; for (int i = 0; i < n; i++) a[i] = readint(); for (int i = 0; i < m; i++) { int tmp = readint(); c[i] = readint(); while (ptr && c[st[ptr - 1]] < c[i]) ptr--; st[ptr] = i, op[ptr++] = tmp; } int pos = c[st[0]]; for (int i = 0; i < pos; i++) b[i] = a[i]; sort(b, b + pos); int l = 0; int r = c[st[0]]; for (int i = 1; i < ptr; i++) { for (int j = c[st[i - 1]]; j > c[st[i]]; j--) a[j - 1] = (op[i - 1] == 1) ? b[--r] : b[l++]; } if (ptr - 1 >= 0) { for (int i = c[st[ptr - 1]]; i > 0; i--) a[i - 1] = (op[ptr - 1] == 1) ? b[--r] : b[l++]; } for (int i = 0; i < n; i++) printf("%d ", a[i]); }