WC2010 重建計畫 長鏈剖分

2022-04-29 23:00:18 字數 1309 閱讀 4522

lg傳送門

又一道長鏈剖分好題。

這題寫點分治的人應該比較多吧,但是我太菜了,只會長鏈剖分。

如果你還不會長鏈剖分的基本操作,可以看看我的長鏈剖分總結。

首先一看求平均值最大,馬上想到套個二分,每次把邊權變為原來的邊權減去二分的答案,看樹上有沒有長度在\(l\)和\(u\)之間的正權鏈就好了。

於是乎問題就轉變成了求樹上權值和最大的鏈,這時馬上想到我們以前做過的一道題p2993 [fjoi2014]最短路徑樹問題

題解,我已經在這道題的題解中把需要的思想講明白了,如果你還不會那道題,最好先去做一做。對於這道題,就是開乙個標記陣列\(b\)記錄增量,注意到我們可選的鏈長是一段區間,考慮用線段樹來維護區間最大值。對於每一時刻,線段樹上維護的資訊都是實際資訊減去當前長鏈頂端的標記值,這樣處理元素間的相對大小關係沒有改變,於是可以維護區間最大值,且保證了單次轉移\(o(logn)\)的複雜度,總的複雜度是\(o(n(logn)^2)\),和點分治一樣。

#include#include#include#define r register

#define i inline

#define d double

using namespace std;

const int s=100003,n=200003,m=400003,inf=1e6;

const d eps=1e-5;

char buf[s],*p1,*p2;

i char gc()

i int rd()

int h[s],s[n],g[n],w[n],d[s],t[s],p[s],q[s],f[s],u[s],c,e,g,n,l,u;

d a[s],b[s],o[m],m;

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

void bld(int k,int l,int r)

void mdf(int k,int l,int r,int x,d v)

r int p=k<<1,q=p|1,m=l+r>>1;

if(x<=m) mdf(p,l,m,x,v);

else mdf(q,m+1,r,x,v);

o[k]=max(o[p],o[q]);

}d qry(int k,int l,int r,int x,int y)

}void dfs2(int x)

if(k>=l) o=max(o,b[l]+qry(1,1,n,l+l,l+min(u,k)));

if(o>=0) g=1;

}i void chk()

int main()

常數被點分暴踩了

WC2010 重建計畫 長鏈剖分 點分治

題目描述 有一棵大小為 n 的樹,給定 l,r 要求找到一條長度在 l,r 的路徑,並且路徑上邊權的平均值最大 1 leq n,l,r leq 10 5 前幾天沉迷初賽來寫幾道資料結構恢復一下 能力,坑填完之後可能就要開始啃思維題了qwq。這個題貌似長鏈剖分和點分複雜度都是 o nlog 2n 的,...

WC2010 重建計畫

嘟嘟嘟 要不這篇部落格我水一下?思路很顯然,點分治 01分數規劃 單調佇列。但就是難寫。點分治的時候我們把每乙個點到重心這條鏈按深度排序,然後對於每乙個點的鏈就有乙個連續深度的區間可以和這條鏈拼上,因為要找一條權值大於 0 的鏈,那就相當於找這個區間的最大值。然後隨著點深度遞增,這個區間就不斷向左移...

WC2010 重建計畫 題解

給定一棵樹,邊有邊權,要求找到一條長度在 l,r 之間的鏈,使得鏈的總價值和除以鏈長最大 顯然,這個式子的形式讓人想到了01分數規劃。於是根據01分數規劃的套路,先二分乙個答案 考慮如何判斷,現在等於把所有邊都減去了乙個 mid 要看有沒有一條價值大於0的長度介於 l,r 的鏈 是不是感覺點分治呼之...