APIO2015 八鄰旁之橋

2022-05-10 21:49:06 字數 3311 閱讀 2080

一條東西走向的穆西河將巴鄰旁市一分為二,分割成了區域 aa 和區域 bb 。

每一塊區域沿著河岸都建了恰好 10000000011000000001 棟的建築,每條岸邊的建築都從 00 編號到 10000000001000000000 。相鄰的每對建築相隔 11 個單位距離,河的寬度也是 11 個單位長度。區域 aa 中的 ii 號建築物恰好與區域 bb 中的 ii 號建築物隔河相對。

城市中有 nn 個居民。第 ii 個居民的房子在區域 p_ipi​的 s_isi​號建築上,同時他的辦公室坐落在 q_iqi​區域的 t_iti​號建築上。乙個居民的房子和辦公室可能分布在河的兩岸,這樣他就必須要搭乘船隻才能從家中去往辦公室,這種情況讓很多人都覺得不方便。為了使居民們可以開車去工作,**決定建造不超過 kk 座橫跨河流的大橋。

由於技術上的原因,每一座橋必須剛好連線河的兩岸,橋梁必須嚴格垂直於河流,並且橋與橋之間不能相交。

當**建造最多 kk 座橋之後,設 d_idi​表示第 ii 個居民此時開車從家裡到辦公室的最短距離。請幫助**建造橋梁,使得 d_1 + d_2 + \cdots + d_nd1​+d2​+⋯+dn​最小。

輸入格式:

輸入的第一行包含兩個正整數 kk 和 nn ,分別表示橋的上限數量和居民的數量。

接下來 nn 行,每一行包含四個引數: p_i, s_i, q_ipi​,si​,qi​和 t_iti​,表示第 ii 個居民的房子在區域 p_ipi​的 s_isi​號建築上,且他的辦公室位於 q_iqi​區域的 t_iti​號建築上。

輸出格式:

輸出僅為一行,包含乙個整數,表示 d_1 + d_2 + \cdots + d_nd1​+d2​+⋯+dn​的最小值。

輸入樣例#1: 複製

1 5

b 0 a 4

b 1 b 3

a 5 b 7

b 2 a 6

b 1 a 7

輸出樣例#1: 複製

24

輸入樣例#2: 複製

2 5

b 0 a 4

b 1 b 3

a 5 b 7

b 2 a 6

b 1 a 7

輸出樣例#2: 複製

22

【資料範圍】

所有資料都保證: p_ipi​和 q_iqi​為字元 「a」 和 「b」 中的乙個, 0 \leq s_i, t_i \leq 10000000000≤si​,ti​≤1000000000 ,同一棟建築內可能有超過 11 間房子或辦公室(或二者的組合,即房子或辦公室的數量同時大於等於 11 )。

子任務 1 (8 分) k = 1k=1

1 \leq n \leq 10001≤n≤1000

子任務 2 (14 分) k = 1k=1

1 \leq n \leq 1000001≤n≤100000

子任務 3 (9 分) k = 2k=2

1 \leq n \leq 1001≤n≤100

子任務 4 (32 分) k = 2k=2

1 \leq n \leq 10001≤n≤1000

子任務 5 (37 分) k = 2k=2

1 \leq n \leq 1000001≤n≤100000

在同一邊的可以直接無視

k=1時

取所有的居民的(家座標+公司座標)/2的所有座標的正中間建一座橋,使所有居民到的距離最小。

k=2時

取每個線段的中點,如果靠近左邊的橋,就往左邊過橋,否則往右邊過橋。

這樣的話,先把線段按l+r排序,如果列舉乙個分割線,左右兩邊分別轉換成為k=1的情況了

用離散+線段樹查詢中位數

f[i]表示1~i中的居民走一座橋

然後從後往前再算一次,答案是min(f[i]+ans(i+1~n)

)如果是k=1直接輸出f[n]

1 #include2 #include3 #include4 #include5 #include6

using

namespace

std;

7 typedef long

long

lol;

8struct

zyys

9d[200001

];12 lol p[400001

];13

intcnt,tot,n,k;

14 lol s[1600001],c[1600001],flag,delta,f[200001

],ans;

15char s1[6],s2[6

];16

bool

cmp(zyys a,zyys b)

1720

void pushup(int

rt)21

25void update(int rt,int l,int r,int

x,lol d)

2633

int mid=(l+r)/2;34

if (x<=mid) update(rt<<1

,l,mid,x,d);

35else update(rt<<1|1,mid+1

,r,x,d);

36pushup(rt);37}

38 lol query(int rt,int l,int r,int

x)39

44int mid=(l+r)/2;45

if (c[rt*2]return s[rt*2]+query(rt*2+1,mid+1,r,x-c[rt*2

]);46

else

return query(rt*2

,l,mid,x);47}

48 lol cal(int

x)49

53int

main()

54 ;

66 p[++tot]=x;p[++tot]=y;67}

68}69 n=cnt;

70 sort(p+1,p+tot+1

);71 cnt=unique(p+1,p+tot+1)-p-1

;72 tot=cnt;

73 sort(d+1,d+n+1

,cmp);

74for (i=1;i<=n;i++)

7579

for (i=1;i<=n;i++)

8085

if (k==1)86

90 memset(s,0,sizeof

(s));

91 memset(c,0,sizeof

(c));

92 ans=f[n];

93for (i=n;i>=1;i--)

9499 cout100 }

APIO2015 八鄰旁之橋

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

APIO2015 八鄰旁之橋

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

APIO2015 八鄰旁之橋

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