1. 程式人生 > 其它 >AcWing 1248. 靈能傳輸 藍橋杯

AcWing 1248. 靈能傳輸 藍橋杯

藍橋杯的一道題:靈能傳輸 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]));

核心就是隔一個一取。

詳細分析見: