AcWing 1248. 靈能傳輸 藍橋杯
阿新 • • 發佈:2022-03-29
藍橋杯的一道題:靈能傳輸 https://www.acwing.com/problem/content/description/1250/
首先是簡化操作,將原陣列轉化為字首和陣列(下標都是從1開始),一次靈能傳輸對原陣列涉及三個數(a[i-1],a[i],a[i+1])的操作,而且操作比較麻煩,但是如果轉化成字首和陣列後等價於(s[i-1]與s[i])交換位置。
原來的目標是求a[i]絕對值最小值,那麼現在的目標變為求s[i]-s[i-1]的絕對值最大值,其中設計的數有s[0~n]
2.由於對陣列可以任意交換位置,經過簡單的思考可以得知如果序列單調(後面就說成單增了),那麼即為所求,那麼對s陣列排序即可。
但是存在一個問題,即s[0],s[n]參與最後求s[i]-s[i-1]的絕對值最大值的計算,但是由於題意可知s[0],s[n]是無法移動的,因此在此情況下怎麼排序呢?
上面兩種方式(這裡假設s0 是小於sn的(如果是大於,swap一下就是一樣的))
右邊更優秀,為何?
簡單理解就是由於s0比sn更小,因此左邊s0到最大值比右邊sn到最大值明顯差值會小一些。
現在問題變為如何排成右邊這種序列?
答案以程式碼呈現:
if(s0 > sn) swap(s0, sn); sort(s, s + n + 1); for(int i = 0; i <= n; i ++ ) if(s[i] == s0) { s0 = i; break; } for(int i = n; i >= 0; i -- ) if(s[i] == sn) { sn = i; break; } memset(st, 0,sizeof st); int l = 0 ,r = n; for(int i = s0; i >= 0; i -= 2) { a[l ++ ] = s[i]; st[i] = true; } for(int i = sn; i <= n; i += 2) { a[r -- ] = s[i]; st[i] = true; } for(int i = 0; i <= n; i ++ ) if(!st[i]) a[l ++ ] = s[i]; LL res = 0; for(int i = 1; i <= n; i ++ ) res = max(res, abs(a[i] - a[i - 1]));
核心就是隔一個一取。
詳細分析見: