BZOJ 4071 巴鄰旁之橋

2022-05-13 10:07:24 字數 1686 閱讀 9369

bzoj 4071傳送門

首先算出能提前算的貢獻

$k=1$:肯定選中間的點,小學數學

$k=2$:對於每對$(x,y)$一定選離$(x+y)/2$近的橋

也就是說將$(x,y)$按$(x+y)/2$的值排序後一定恰有乙個分割點使得兩邊選擇不同的橋!

考慮如何如何快速列舉所有分割點時的答案:

需要支援插入、刪除、求中位數及兩邊的和,明顯選擇$splay$來維護(求和更容易些)

這樣先將所有數對加進乙個$splay$,再不斷將其中的數移向另一棵$splay$即可

注意:可能以前的$splay$板子容易出不少鍋啊……

首先$update$時最好對$z$進行判斷,然後$splay$最後也要$pushup$否則會在樹高低時不更新$size$

#include using

namespace

std;

#define x first

#define y secondtypedef

double

db;typedef

long

long

ll;typedef pair

p;const

int maxn=2e5+10;//

注意範圍

const ll inf=1

<<30

;struct

splay

void rotate(int

x)

void splay(int x,int

up)

if(!up) rt=x;

//!!!!!!!!

update(x);//

可能f[x]=up,但也要update

}

void insert(int

x)

splay(k,0);

}void find(int

x)

int kth(int

x)

}//不用加邊界的刪除法

void del(int

x)

else

//由於後面沒有splay了要update

update(rt);

}ll query()

}s1,s2;

char a[10],b[10

];ll res=1ll<<60

,pre;

intn,x,y,k,tot;p dat[maxn];

bool cmp(p a,p b);

intmain()

//注意特判!!!

if(!tot) return printf("

%lld

",pre),0

; sort(dat+1,dat+tot+1

,cmp);

for(int i=1;i<=tot;i++)

s1.insert(dat[i].x),s1.insert(dat[i].y);

if(k==1) return printf("

%lld

",s1.query()+pre),0

;

for(int i=1;i<=tot;i++)

printf(

"%lld

",res+pre);

return0;

}

BZOJ4071 八鄰旁之橋(線段樹)

bzoj許可權題,洛谷鏈結 既然 k 2 那麼,突破口就在這裡 分類討論 k 1 這。不就是中位數嗎。直接把所有起點重點排個序,算下中位數就行啦 k 2 似乎不好搞了 orz zsy dalao 我太弱了 我就是乙個vegetable chicken zsy看一眼就會做 所以 define brig...

4071 Apio2015 巴鄰旁之橋

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

BZOJ4071 Apio2015 巴鄰旁之橋

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