Luogu6670 清華集訓2016 汽水

2022-05-17 14:43:10 字數 3175 閱讀 7306

luogu6670 [清華集訓2016] 汽水

網上說這道題是點分治

反正蒟蒻用邊分治切了這道題。

題意就是求一條鏈,使它的平均權值與\(k\)的絕對值最小。

設任意一條鏈為\(\\)。

求:\[\min \lvert \frac^t w_i}-k \rvert

\]我們考慮二分答案,然後我們需要判斷是否存在符合條件的鏈。

我們二分的是\(\lvert \frac^t w_i}-k \rvert\),它是非負的。

如果我們二分到\(mid\)是合法的,應當存在鏈滿足:

\[\lvert \frac^t w_i}-k \rvert \le mid

\]把\(k\)加入分母中。

\[\frac^t w_i}-k=\\

\frac^t w_i)-tk}=\\

\frac^t (w_i-k)}

\]拆開絕對值。

\[-mid \le \frac^t (w_i-k)} \le mid

\]\[\begin

\frac^t (w_i-k-mid)} \le 0\\

\frac^t (w_i-k+mid)} \ge 0

\end

\]我們可以對一條邊定兩個邊權\(w_i-k-mid,w_i-k+mid\),那麼對於一條鏈,我們會獲得兩個鏈長\(l1,l2\)。

我們需要滿足\(l1 \le 0,l2 \ge 0\)。

考慮邊分治,對於兩端的鏈,自己作為一條鏈統計貢獻,與另乙個連通塊中的鏈合併仍需要統計貢獻。

現在就需要解決快速鏈合併。

我們現在可以轉化為序列問題了。

給你兩個由數對\((x,y)\)組成的序列\(a,b\),你需要判斷是否存在乙個\(a\)中的數對\(p\)和\(b\)中的數對\(q\),滿足\(p_x+q_x \le 0,p_y+q_y \ge 0\)。

我們可以先把兩個序列按\(x\)從小到大排序。

那麼對於乙個\(a\)中的數對\(p\),與\(p\)滿足\(p_x+q_x \le 0\)的\(b\)中數對一定在一段連續的區間中,我們只需要比較\(p_y\)和這段區間中\(y\)的最大值匹配即可。

觀察發現,如果我們對\(a\)從大到小掃一遍,那麼合法的區間一定從\([1,z]\)開始(\(z\)可以小於\(1\),表示不存在合法方案),\(z\)不斷擴大,而左端點\(1\)不改變,直接乙個指標掃過去就好了。

注意點:

\(1.\)由於單個點不能算作一條鏈,我們必須判斷乙個節點是否走過一條邊,否則不能加入匹配序列中,而在邊分樹上走過一些虛點後到達它們的父親節點仍然沒有走過一條邊,需要特判。

\(2.\)二分答案時,由於只需要保留整數,我們按整數來二分。這道題需要向下取整,我們二分到的答案可能需要\(-1\),比如\(1.5\)二分到的答案為\(2\),那麼我們對二分得到的答案進行一次邊分治,只要判斷是否有不取等號的解即可(操作就是把所有的\(\le,\ge\)改成\(<,>\))。

\(code:\)

#include#include#include#include#include#define n 50005

#define m 100005

#define ll long long

#define pr pair#define lpr pair#define mp make_pair

using namespace std;

const ll inf=1919191919191919;

const int iinf=1000000009;

vector< pr >e[n];

#define it vector< pr > :: iterator

int n,x,y,rt,rtsz;

ll k,z,mx,mn,mid,ans;

int tot=1,cnt;

bool flag,flag2;

struct node

}e[m << 1];

int fr[m],sz[m],cp[m];

bool vis[m << 1];

ll cdp1[m],cdp2[m];

int qcp,cc[2];

lpr c[2][n];

void add(int x,int y,ll z)

void add_edge(int x,int y,ll z)

void build(int u,int f)

build(v,u);

}}void getrt(int u,int f,int rn)

}void solve(int u,int s)

dfs2(v2,0,1);

for (int i=1;i<=cc[0];++i)

if ((!flag2 && c[0][i].first<=0 || flag2 && c[0][i].first<0) && (!flag2 && c[0][i].second>=0 || flag2 && c[0][i].second>0))

for (int i=1;i<=cc[1];++i)

if ((!flag2 && c[1][i].first<=0 || flag2 && c[1][i].first<0) && (!flag2 && c[1][i].second>=0 || flag2 && c[1][i].second>0))

sort(c[0]+1,c[0]+cc[0]+1),sort(c[1]+1,c[1]+cc[1]+1);

ll mx=-inf;

int l=1;

for (int i=cc[0];i;--i)

if (l!=1 && (!flag2 && mx+c[0][i].second>=0 || flag2 && mx+c[0][i].second>0))

}int kt=rt,ts=s-sz[v1];

solve(v1,sz[v1]);

if (flag)

solve(v2,ts);

vis[kt]=vis[kt^1]=false;

}bool check()

int main()

mid=ans;

flag2=true;

if (ans && check())

--ans;

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

return 0;

}

P6670 清華集訓2016 汽水

p6670 清華集訓2016 汽水 給一棵樹,邊有邊權,要求找到一條路徑使得其平均值和 k 最接近。首先樹上路徑容易想到點分治。然後發現這可以套乙個 0 1 分數規劃,於是我們可以把所有的邊權減掉 k 再二分 mid 現在的問題就是判斷了。我們發現答案具有單調性,於是我們可以排序過後雙指標維護路徑。...

清華集訓2016 汽水

試題描述 牛牛來到了乙個盛產汽水的國度旅行。這個國度的地圖上有n個城市,這些城市之間用 n 1 條道路連線,任意兩個城市之間,都存在一條路徑連線。這些城市生產的汽水有許多不同的風味,在經過道路 i 時,牛牛會喝掉 wi 的汽水。牛牛非常喜歡喝汽水,但過量地用汽水是有害健康的,因此,他希望在他旅行的這...

清華集訓2016 資料互動

題目描述 乙個簡單的網路系統可以被描述成一棵無根樹。每個節點為乙個伺服器。連線伺服器與伺服器的資料 線則看做一 條樹邊。兩個伺服器進行資料互動時,資料會經過連線這兩個伺服器的路徑上的所有服務 器 包括這兩個伺服器 自身 每個資料互動請求都有乙個非負的重要度,越重要的請求顯然需要得 到越高的優先處理權...