APIO2015 八鄰旁之橋

2022-05-05 18:30:08 字數 2592 閱讀 5254

傳送門

這道題看起來十分的不可做……可能是我數學太差智商太低了orz。

首先如果乙個人的家和辦公室在同一側那就完全不用考慮,把結果記下來就行。

然後我們先考慮k=1的情況。因為只能建1座橋,那麼我們發現(除去過橋乙個單位長度不算)答案就是sigma(abs(ai-x)  + abs(bi-x)),其中ai,bi表示區間的開始和末尾,這樣我們發現區間的開始和末尾並沒有本質上的區別……所以我們直接把所有端點都排個序然後直接找到中位數(r),答案就是sigma(r-ai) (i<=r) + sigma(ai - r) (i >= r) 然後實際中計算的時候非常的簡潔,只要把所有小於中位數的答案加起來,把所有大於中位數的答案也加起來,兩者差值+預處理結果就是答案。

那麼k=2的時候怎麼辦呢?這個我又沒想到……首先我們可以這麼想,找到每個區間的中點,如果中點更靠近左邊的橋那麼就從左邊過橋,否則從右邊過橋(這個還是比較顯然的)。於是我們先把所有區間按照l+r從小到大排序(中點座標),再選擇列舉乙個分割線(分割線左邊的全部從左邊過橋,右邊的從右邊過橋),這樣我們就把兩邊分成了兩個k=1的情況。

之後的問題就是怎麼快速計算。我們使用線段樹維護中位數(r),維護區間內元素個數(k)和距離總和(s),這樣的話乙個區間的答案就是k*loc[r] - s + s1 - k1*loc[r],(前面是中位數左邊的,後面是中位數右邊的),loc記錄這個點所對應的位置。然後分割線另一端的也一樣,開兩個線段樹維護即可。

一開始首先把右邊的樹填滿,之後分割線每移動一次,把對應的從右樹中刪除,加到左樹里。

然後這題有倆坑,第乙個是有可能區間的末尾比起點小,這時候要先swap一遍,第二個就是有可能不需要過河…………這樣的時候直接特判輸出就行…………

看一下**。

#include#include

#include

#include

#include

#include

#include

#include

#define pr pair#define mp make_pair

#define fi first

#define sc second

#define rep(i,a,n) for(int i = a;i <= n;i++)

#define per(i,n,a) for(int i = n;i >= a;i--)

#define enter putchar('\n')

using

namespace

std;

typedef

long

long

ll;const

int m = 100005

;const

int n = 10000005

;const ll inf = 1000000000000000009;

intread()

while(ch >='

0' && ch <= '9'

)

return ans *op;

}int loc[m<<2

],n,k,s,ter,tot,cnt,len;

//tot records the number of loc,cnt records the number of segments(node)

char s1[5],s2[5

];ll ans,minn =inf;

struct

node

}d[m

<<2

];struct

seg

int mid = (l+r) >> 1

;

if(pos <= mid) modify(p<<1

,l,mid,pos,x);

else modify(p<<1|1,mid+1

,r,pos,x);

v[p] = v[p<<1] + v[p<<1|1

]; sz[p] = sz[p<<1] + sz[p<<1|1

]; }

int find(int p,int l,int r,int

x)

ll size(

int p,int l,int r,int kl,int

kr)

ll sum(

int p,int l,int r,int kl,int

kr)

}t[2];//

0 records left ,1 records right

void

work()

void

solve()

rep(i,

1,cnt) t[1].modify(1,1,len,d[i].l,1),t[1].modify(1,1,len,d[i].r,1

); rep(i,

1,cnt)

printf(

"%lld\n

",minn +ans);

}int

main()

if(!cnt)

if(k == 1

) work();

else

solve();

return0;

}

APIO2015 八鄰旁之橋

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

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 的距離,...