APIO2015 八鄰旁之橋

2022-05-03 18:27:11 字數 1437 閱讀 8441

傳送門

題目大意

兩條水平的直線,距離為$1$,給定$n$對座標,座標是在某一條直線上的某乙個位置,你可以建立$k$豎直的直線$(k\leq 2)$,

要使得每對座標只沿著直線移動從第乙個座標到第二個座標的距離和最小。

題解首先可以求出在一對座標在同一條水平直線上的代價,對於需要跨越的,都經過了豎直直線的$1$的距離,也都預先算出來。

考慮$k=1$的情況,設每對座標的水平位置是$(x_1,x_2)$,直線放在了$pos$的位置,那麼代價是$\sum(|x_1-pos|+|x_2-pos|)$。

發現$x_1$,$x_2$對答案的貢獻是獨立的,且很顯然當$pos$取所有$x_1,x_2$的中位數時,距離最小。

如何擴充套件到$k=2$?

設條豎直線的座標是$pos_1,pos_2$(不妨設$pos_1

考慮對所有對座標按照$x_1+x_2$,排序,這樣一定滿足選擇$pos_1$的一定是乙個字首,選擇$pos_2$的一定是乙個字尾,那麼問題就轉化為兩個$k=1$的子問題了。

直接列舉字首字尾的劃分位置,用權值線段樹維護左右部分中位數大小,用字首和優化算出所有數到中位數的距離即可。

複雜度$o(n\log n)$。

#include#include#include#include#include#define ll long long

#define m 100020

using namespace std;

namespace io if(x<0) x=-x,putchar('-');

while(x) ss[++top]=x%10,x/=10;

while(top) putchar(ss[top]+'0'),--top;

} int read()

}using namespace io; char s1[20],s2[20];

int rt[2],n,m,a[m<<2],b[m<<2],k,cnt[2],od[m];

int g[m<<2],l[m<<2][2],r[m<<2][2],ct[m<<2][2];

ll res,sum[m<<2][2];

bool cmp(int x,int y)

void ins(int &x,int l,int r,int pos,int dt,int kd)

int gtnum(int x,int l,int r,int rk,int kd)

ll qry(int x,int l,int r,int pos,int kd)

ll calc(ll kd)

ll solve2() ll ans=calc(0);

for(int i=n;i;i--) return ans;

}int main() write(((k&1)?solve1():solve2())+res);

putchar('\n');return 0;

}

APIO2015 八鄰旁之橋

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

APIO2015 八鄰旁之橋

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

APIO2015 八鄰旁之橋

注意到 k 1,2 於是我們可以從簡單的 k 1 開始入手。可以發現家和辦公室在同一邊的人不管建不建橋都是無所謂的,因此下面我們只需要考慮不在同一邊的人,假設橋的位置在 d 那麼答案可以簡單的表示為 sum limits n s i d t i d 這可以看作是 2n 個在數軸上的點到 d 的距離,...