BZOJ4071 APIO2015 八鄰旁之橋

2022-03-29 17:44:54 字數 3236 閱讀 3611

bzoj4071: [apio2015]八鄰旁之橋

這個題也變成了許可權題,不是很懂為什麼。。。

反正沒錢氪金。。。

這裡附上洛谷的題面:

洛谷p3644 [apio2015]八鄰旁之橋

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

每一塊區域沿著河岸都建了恰好$1000000001$棟的建築,每條岸邊的建築都從$ 0$ 編號到 $1000000000$。相鄰的每對建築相隔 $1$ 個單位距離,河的寬度也是 $1$ 個單位長度。

區域 $a$ 中的$ i$ 號建築物恰好與區域 $b$ 中的 $i$ 號建築物隔河相對。

城市中有$ n$ 個居民。第 $i$ 個居民的房子在區域$ p_i$的$ s_i$號建築上,同時他的辦公室坐落在$ q_i$區域的$ t_i$​號建築上。

乙個居民的房子和辦公室可能分布在河的兩岸,這樣他就必須要搭乘船隻才能從家中去往辦公室,這種情況讓很多人都覺得不方便。為了使居民們可以開車去工作,**決定建造不超過 kk 座橫跨河流的大橋。

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

當**建造最多$ k$ 座橋之後,設 $d_i$表示第$ i$ 個居民此時開車從家裡到辦公室的最短距離。請幫助**建造橋梁,使得$ d_1 + d_2 + \cdots + d_n$​最小。

輸入格式:

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

接下來 nn 行,每一行包含四個引數:$p_i, s_i, q_i$​和$ t_i$,表示第$ i$ 個居民的房子在區域 $p_i$的$ s_i$號建築上,且他的辦公室位於 $q_i$區域的 $t_i$號建築上。

輸出格式:

輸出僅為一行,包含乙個整數,表示$ d_1 + d_2 + \cdots + d_n$的最小值。

輸入樣例#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_i$和 $q_i$為字元 「a」 和 「b」 中的乙個, $0 \leq s_i, t_i \leq 1000000000$,同一棟建築內可能有超過$ 1$ 間房子或辦公室(或二者的組合,即房子或辦公室的數量同時大於等於 $1$)。

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

$1 \leq n \leq 1000$

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

$1 \leq n \leq 100000$

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

$1 \leq n \leq 100$

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

$1 \leq n \leq 1000$

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

$1 \leq n \leq 100000$

又是一道把兩個相似的題強行拼接在一起的題。。。

直接分類討論:

當$k==1$的時候:

如果工作地點在一側,那麼路程就是$r-l$。

然後我們對於不在一側的線段端點求個中位數,這樣肯定能使總路程最小。

不過,$k==1$的情況沒有必要線段樹,直接丟進陣列裡排個序,就可以求出中位數了。

當$k==2$的時候:

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

列舉乙個分割點,然後兩邊都是$k==1$的情況,用線段樹求$\sum|\text-\text|$。

附**:(我分了兩個$namespace$來寫)

#include#include#include#define maxn 1000010

using namespace std;

int n,k;

int top=0,stack[maxn];

long long ans=0;

inline int read()

while(c>='0'&&c<='9')

return date*w;

}inline long long abs(const long long x)

namespace one

else if(p==1)swap(x,y);

m++;

stack[++top]=x;stack[++top]=y;

} sort(stack+1,stack+top+1);

int mid=stack[top>>1];

for(int i=1;i<=top;i++)ans+=abs(mid-stack[i]);

printf("%lld\n",ans+m); }}

namespace two

}line[maxn];

struct segment_treea[maxn<<2];

inline void add_line(int x,int y)

inline void pushup(int rt)

void buildtree(int l,int r,int rt)

void update(int k,int v,int rt)

long long query(int k,int rt)

inline long long ask(int x)

void work()

long long minn=s[num];

buildtree(1,top,1);

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

printf("%lld\n",minn+ans);

} void main()

ans++;

stack[++top]=x;stack[++top]=y;

if(x>y)swap(x,y);

add_line(x,y);

} if(!num)

sort(line+1,line+num+1);

sort(stack+1,stack+top+1);

top=unique(stack+1,stack+top+1)-stack-1;

work(); }}

int main()

BZOJ4071 Apio2015 巴鄰旁之橋

首先對於家和公司在同一側的預處理掉,這樣就只剩家和公司不在同一側的情況了。if k 1 ans abs x pos abs y pos 注意到與x,y是否在兩側無關,所以用經典的中位數處理思想sort一遍取中位數貪心即可。else 好久不寫splay,練習了一發 include include in...

4071 Apio2015 巴鄰旁之橋

一條東西走向的穆西河將巴鄰旁市一分為二,分割成了區域 a 和區域 b。每一塊區域沿著河岸都建了恰好 1000000001 棟的建築,每條岸邊的建築都從 0 編號到 1000000000。相鄰的每對建築相隔 1 個單位距離,河的寬度也是 1 個單位長度。區域 a 中的 i 號建築物恰好與區域 b 中的...

BZOJ 4071 巴鄰旁之橋

bzoj 4071傳送門 首先算出能提前算的貢獻 k 1 肯定選中間的點,小學數學 k 2 對於每對 x,y 一定選離 x y 2 近的橋 也就是說將 x,y 按 x y 2 的值排序後一定恰有乙個分割點使得兩邊選擇不同的橋!考慮如何如何快速列舉所有分割點時的答案 需要支援插入 刪除 求中位數及兩邊...