APIO2015 巴鄰旁之橋(二叉堆 中位數)

2022-03-17 00:33:59 字數 1288 閱讀 1372

鏈結

先特判掉在同乙個區域內的人,他們不需要橋,下面不考慮他們

k==1時,即只有一座橋,假設它的位置是k,那麼對於每個人i,他的貢獻是\(|k-ai|+|k-bi|\),可以看出這兩部分的結構是一樣的,可以分開看。於是問題就變成了有2n個人,求乙個位置k,使得\(\sigma_^|ai-k|\)最小,這顯然是求它們的中位數,sort一遍即可

k2時,對於乙個人i,\((ai+bi)/2\)離哪個橋近就從哪個橋過,這樣一定是最優的(顯然),於是對\((ai+bi)\)排個序,左邊一部分人一定從左邊的橋過,右邊的一部分人從右邊的橋過,我們只需要知道這個分界點在**就行了。

於是從1~n列舉這個分界點,兩邊分別按照k1的方法來做即可

但是問題是這樣做是\(n^2\)的複雜度(列舉n*求值n),考慮優化一下求中位數的過程

動態維護中位數,用兩個堆維護即可,咕咕模板

code:

#include#define n 100005

using namespace std;

typedef long long ll;

const ll inf = 10000000000000000;

int k,n,p;

ll ans,tpr,a[n<<1];

ll rsum,lsum,sum[n];

struct node

nd[n];int cnt;

priority_queuefro;

priority_queue,greater> bac;

bool cmp(node a,node b)

else

while(abs((int)bac.size()-(int)fro.size())>1)

else

}}int main()

nd[++cnt]=(node);

a[++p]=x;

a[++p]=y;

} sort(a+1,a+p+1);

for(int i=1;i<=p;++i) tpr+=abs(a[i]-a[cnt]);

if(k==2)

while(!fro.empty()) fro.pop();

while(!bac.empty()) bac.pop();

rsum=lsum=0;

for(int i=cnt;i>=1;--i)

for(int i=1;i<=cnt;++i) tpr=min(tpr,sum[i]);

} cout

}

APIO2015 八鄰旁之橋

傳送門 題目大意 兩條水平的直線,距離為 1 給定 n 對座標,座標是在某一條直線上的某乙個位置,你可以建立 k 豎直的直線 k leq 2 要使得每對座標只沿著直線移動從第乙個座標到第二個座標的距離和最小。題解首先可以求出在一對座標在同一條水平直線上的代價,對於需要跨越的,都經過了豎直直線的 1 ...

APIO2015 八鄰旁之橋

傳送門 這道題看起來十分的不可做 可能是我數學太差智商太低了orz。首先如果乙個人的家和辦公室在同一側那就完全不用考慮,把結果記下來就行。然後我們先考慮k 1的情況。因為只能建1座橋,那麼我們發現 除去過橋乙個單位長度不算 答案就是sigma abs ai x abs bi x 其中ai,bi表示區...

APIO2015 八鄰旁之橋

一條東西走向的穆西河將巴鄰旁市一分為二,分割成了區域 aa 和區域 bb 每一塊區域沿著河岸都建了恰好 10000000011000000001 棟的建築,每條岸邊的建築都從 00 編號到 10000000001000000000 相鄰的每對建築相隔 11 個單位距離,河的寬度也是 11 個單位長度...