日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

2021年第十二届蓝桥杯 - 省赛 - C/C++大学B组 - I.双向排序

發布時間:2024/5/17 c/c++ 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2021年第十二届蓝桥杯 - 省赛 - C/C++大学B组 - I.双向排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2021年第十二屆藍橋杯 - 省賽 - C/C++大學B組 - I.雙向排序


Ideas

題目中給出了兩種操作:

  • 當 pi = 0 時,表示將 a1, a2, · · · , aqi 降序排列;
  • 當 pi = 1 時,表示將 aqi , aqi+1, · · · , an 升序排列。
  • 按照題目暴力排序應該可以騙一點分,但如果想AC,就需要優化算法。可以根據測試用例的范圍:1 ≤ n, m ≤ 100000,估計一下時間復雜度要控制在O(nlog n)。

    首先對于連續的p=0,即:pi=0 qi=a;pi+1=0 qi+1=b。如果b>a,那么(pi, qi)的操作將無效,因為(pi+1, qi+1)已經將(pi, qi)的范圍包含了。同理,如果pi+2=0; qi+2=c,而b>c,那么pi+2和qi+2的操作也將無效。

    然后對于連續的p=1,即:pi=1 qi=a;pi+1=1 qi+1=b。同理,如果a<b,那么(pi+1, qi+1)的操作將無效,因為(pi, qi)已經將(pi+1, qi+1)的范圍包含了。

    因此我們可以總結出,對于連續的p=0和p=1,只需要分別保留q最大和q最小的那次操作即可。

    有了上面的簡化之后,整個操作序列其實就被壓縮成了p=0和p=1的交替操作,由于一開始的序列是升序排列的,所以第一個有效操作肯定是pi = 0,讓我們將某一個前綴降序排列。

    我們舉個例子來分析一下,令n=9,即[1, 2, 3, 4, 5, 6, 7, 8, 9]:

  • p=0,q=3,即1~3位置降序排,變成了[3, 2, 1, 4, 5, 6, 7, 8, 9]
  • p=1,q=7,即7~9位置升序排,不發生變化,還是[3, 2, 1, 4, 5, 6, 7, 8, 9]
  • p=0,q=6,即1~6位置降序排,變成了[6, 5, 4, 3, 2, 1, 7, 8, 9]
  • p=1,q=4,即4~9位置升序排,變成了[6, 5, 4, 1, 2, 3, 7, 8, 9]
  • p=0,q=5,即1~5位置降序排,變成了[6, 5, 4, 2, 1, 3, 7, 8, 9]
  • 通過這個例子我們可以發現一些規律,有些數字的位置被固定下來了,基本不會變。

    為了會這樣呢?我們分析一下。

    對于第1次有效操作,假設是將[1, x]降序排列,由于最初我們的數據都是升序的,所以?b∈[x+1, n] > ?a∈[0, x]。

    那么之后我們對[y, n]升序排列(y<=x) 的話其實[x, n]這部分是不變的。

    這是因為[y, x] ∈ [0, x] < [x+1, n],所以[x+1, n]這部分的任意值是始終大于[y, x]中的任意值。

    因此我們對[y, n]升序排序的話,其實[x, n]這部分不會挪動位置,換句話說,[x, n]已經被固定下來了。

    同理,[1, y]其實也被固定下來了,所以說我們不停的操作其實就是不停的從數組的兩邊向中間固定元素。

    我們可以用兩個變量 left 和 right,分別表示數組的兩邊被固定下來的位置,left 不斷增加,right 不斷減小,最終數組被固定。

    最后扣一下邊界,如果最后一次操作是前綴降序,那相當于確定一個[x, n],我們手動把一個[i, x]確定下來就可以了,反之亦然。

    Code

    C++

    #include <iostream>using namespace std;const int N = 100010; pair<int, int> stk[N]; int ans[N];int main() {int n, m, top = 0;cin >> n >> m;while (m--) {int p, q;cin >> p >> q;if (p == 0) {while (top && stk[top].first == 0) {q = max(q, stk[top--].second);}while (top >= 2 && stk[top - 1].second <= q) {// 如果當前操作比上一次相同操作的范圍要大,那此次操作的前兩次操作都將被無效化 top -= 2;}stk[++top] = {0, q};} else if (top) {while (top && stk[top].first == 1) {q = min(q, stk[top--].second);}while (top >= 2 && stk[top - 1].second >= q) {// 如果當前操作比上一次相同操作的范圍要大,那此次操作的前兩次操作都將被無效化 top -= 2;}stk[++top] = {1, q};}}int left = 1, right = n, k = n;for (int i = 1; i < top + 1; i++) {if (stk[i].first == 0) {while (right > stk[i].second && left < right + 1) {ans[right--] = k--;}} else {while (left < stk[i].second && left < right + 1) {ans[left++] = k--;}}if (left > right) {break;}}if (top % 2) {while (left < right + 1) {ans[left++] = k--;}} else {while (left < right + 1) {ans[right--] = k--;}}for (int i = 1; i < n + 1; i++) {cout << ans[i] << " ";}return 0; }

    Python

    if __name__ == '__main__':n, m = map(int, input().split())nums = [i + 1 for i in range(n)]seq = [] # 用于存儲操作序列for _ in range(m):p, q = map(int, input().split())if p == 0:while seq and seq[-1][0] == 0: # 如果是連續的 p = 0,只取最大的 qq = max(q, seq[-1][1])seq.pop()while len(seq) > 1 and seq[-2][1] <= q: # 如果此次前綴降序的右邊界大于上一次前綴降序的右邊界,可以省略在此之前的兩次操作seq.pop()seq.pop()seq.append((0, q))elif seq: # seq 不為空保證這是有一個 p = 0 之后的 p = 1 操作while seq and seq[-1][0] == 1: # 如果是連續的 p = 1,只取最小的 qq = min(q, seq[-1][1])seq.pop()while len(seq) > 1 and seq[-2][1] >= q: # 如果此次后綴升序的左邊界小于上一次后綴升序的右邊界,可以省略在此之前的兩次操作seq.pop()seq.pop()seq.append((1, q))k, left, right = n, 1, nfor i in range(len(seq)):if seq[i][0] == 0: # 前綴降序while right > seq[i][1] and left <= right:nums[right - 1] = k # 從后往前設置right -= 1k -= 1else: # 后綴升序while left < seq[i][1] and left <= right:nums[left - 1] = k # 從前往后設置left += 1k -= 1if left > right:breakif len(seq) % 2: # 最后一次操作為前綴降序while left <= right:nums[left - 1] = kleft += 1k -= 1else: # 最后一次操作為后綴升序while left <= right:nums[right - 1] = kright -= 1k -= 1print(' '.join(map(str, nums)))

    總結

    以上是生活随笔為你收集整理的2021年第十二届蓝桥杯 - 省赛 - C/C++大学B组 - I.双向排序的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。