給定乙個數軸,以及數軸上的 \(n\) 個點(這些點可能坐落在同一座標上),第 \(i\) 個點的座標為 \(a_i\) 。現在要在數軸上找 \(k\) 個點,第 \(i\) 個點的座標為 \(x_i\) 。求這 \(k\) 個點到原數軸上 \(n\) 個點距離和的最小值,即 \(min(\sum_^ \sum_^ |x_i - a_j|)\).
注:\(n,\ a_i \leq 10^6,\ k \leq n\)
首先,最容易想到的就是暴力模擬。迴圈列舉座標,對於每個座標,求出其到 \(n\) 個點的距離和。最後再將距離和公升序排列。時間複雜度 $o(an) = $tle
現在從兩個方向考慮優化:
減少列舉數量。也就是減少 \(x\) 的列舉數量。
減少計算過程。也就是降低求 \(x_i\) 到 \(a_j\) 距離和的複雜度。
而由於 \(x\) 與其他點的距離沒有方便計算的函式表示,所以減少列舉數量是不現實的(可能是因為我太弱了)
那麼怎樣減少計算過程呢??
設乙個點 \(x\) 到所有 \(a\) 的距離和為 \(s\)。
我們可以發現,如果 \(x\) 往前走乙個單位長度,那麼它與它前面點的距離就都會加一,與後面點的距離都會減一。
設 \(x\) 往前移動一位後, \(x\) 前面有 \(c\) 個點,後面有 \(n - c\) 個點。
那麼,距離就會變為:\(s + c - (n - c)\)。
所以,我們在列舉訊號站座標的時候,就可以順帶著將訊號站到其他點的距離用 \(o(1)\) 算出來
時間複雜度為 \(o(a)\)
**大概長這樣(由於空間有限,就不在這裡放了) wrong code
然後就驚喜的發現wa了乙個點 ...
發現我**中的錯誤是在一天之後了。我忽然發現,訊號站是有可能建在負數座標上的,舉個栗子:
數軸上點的座標為: \(a = [0, 0, 0, 0, 0]\)
我們要選擇5個訊號站。
那麼,最優解應該是 \(x = [0, 1, 2, -1, -2]\).
這樣,我們的訊號站就選到了負數點上。
這樣,我們只需要將訊號站列舉起點換成 \(-10^6\) (因為 \(k \leq 10^6\) 嘛)。由於陣列下標不能是負數,所以我們在陣列上加上乙個偏移量 \(delta\),讓陣列下標變成正數即可。
#include #include #include #include using namespace std;
typedef long long ll;
const int n = 1000010, m = n << 1;
ll f[m];
int p[n];
int delta = 1e6;
int n, m;
int map[n];
int main()
sort(p + 1, p + n + 1);
int l = 0, r = n;
f[0] = s;
for (int i = -1e6 + 1; i <= 1e6; i ++ )
sort(f, f + 2000000 - 1);
ll res = 0;
for (int i = 0; i < m; i ++ )
res += f[i];
printf("%lld\n", res);
return 0;
}
bzoj4998 星球聯盟
description 在遙遠的s星系中一共有n個星球,編號為1 n。其中的一些星球決定組成聯盟,以方便相互間的交流。但是,組成 聯盟的首要條件就是交通條件。初始時,在這n個星球間有m條太空隧道。每條太空隧道連線兩個星球,使得它們能 夠相互到達。若兩個星球屬於同乙個聯盟,則必須存在一條環形線路經過這...
BZOJ 4998 星球聯盟
題意 給一張無向圖,並不斷加邊 u,v 並詢問 u,v 是否位於同乙個雙聯通分量裡,若位於同一雙聯通分量,輸出這個雙聯通分量的 size 使用並查集 lct維護。有兩套並查集 s1是用來維護每個點歸屬哪乙個強連通分量,每個點的祖先是這個強連通分量的代表節點,同時代表節點儲存這個強連通分量的 size...
hdu 4998 矩陣表示旋轉
乙個旋轉變換可以轉化為乙個三維矩陣的變化 繞 x,y 旋轉角度r,執行十次,求等價旋轉點和角度 繞原點矩陣如下 由於是繞 x,y x1 x x0 cos0 y y0 sin0 x0 y1同理,那麼第三行前兩列即為x0 1 cos r y0 sin r 和y0 1 cos r x0 sin r 最後根...