分數規劃和長鏈剖分大體思路大佬們已經講得很清楚了
奈何我太蒟了被有個問題卡了我很久
就是怎麼分配每個子樹對應的線段樹的空間
當我們正在處理x點時
先遞迴處理完它的重兒子也就是y
然後直接讓x繼承y的資料
若y對應的陣列長這樣子
我們發現在y這棵樹中
x為距離1的點就是y距離0的點
x為距離2的點就是y距離1的點…
所以這個顯然就是
我們先遍歷重兒子所形成的dfs序
其中每一條長鏈都對應的一段區間
所以這道題就是對dfs序建一顆線段樹
x子樹中 距離為n的點的最大權值
對應的是線段樹中第dfn[x]+n個元素
我也搞不懂為什麼我在這種顯zhi然zhang的地方卡這麼久
最外層的二分乙個log 線段樹乙個log
o (n
log2
n)o(nlog^2n)
o(nlog
2n)最後**
#include
#define n 100100
#define m 200100
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define mid ((l+r)>>1)
using
namespace std;
typedef
long
long ll;
const
double inf=
-5e11
*1.0
;int n,minn,maxx;
int f[n]
,nxt[m]
,data[m]
,num;
int dfn[n]
,mdep[n]
,dep[n]
,son[n]
,fa[n]
,len[n]
,root,ti;
double rr,mm,lst[n]
,far[m]
,dis[n]
;int posi[n]
;bool ans;
struct _tr
inline
void
updata
(int pos,
double c,
int rt=1,
int l=1,
int r=n)
if(pos<=mid)
else
push_up
(rt);}
inline
double
query
(int l,
int r,
int rt=1,
int l=1,
int r=n)
inline
void
build
(int rt=1,
int l=1,
int r=n)
build
(lson)
;build
(rson);}
}q;void
inline
add(
int x,
int y,
int z)
inline
void
dfs(
int x)
} len[x]
=mdep[x]
-dep[x];}
inline
void
dfs2
(int x)
int y;
for(
int i=f[x]
;i;i=nxt[i])}
inline
void
solve
(int x)
for(
int i=f[x]
;i;i=nxt[i])}
for(
int j=
0;j<=
min(len[y]
,maxx)
;j++)}
}if(len[x]
>=minn)}}
void
get_ans()
else
}printf
("%.3lf"
,l);
}int
main()
root=
rand()
%n+1
;dfs
(root)
;dfs2
(root)
;get_ans()
;return0;
}
P4292 WC2010 重建計畫
傳送門 首先這玩意兒很明顯是分數規劃,二分乙個答案 mid 邊權變為 w i mid 然後看看能不能找到一條路徑長度在 l,r 之間,且邊權總和非負,這個可以轉化為求一條滿足條件的邊權最大的路徑 這個實際上可以用點分做,用單調佇列可以優化到 o nlog 2n 然而我不知道為什麼寫掛掉了所以這裡就不...
WC2010 重建計畫
嘟嘟嘟 要不這篇部落格我水一下?思路很顯然,點分治 01分數規劃 單調佇列。但就是難寫。點分治的時候我們把每乙個點到重心這條鏈按深度排序,然後對於每乙個點的鏈就有乙個連續深度的區間可以和這條鏈拼上,因為要找一條權值大於 0 的鏈,那就相當於找這個區間的最大值。然後隨著點深度遞增,這個區間就不斷向左移...
WC2010 重建計畫 題解
給定一棵樹,邊有邊權,要求找到一條長度在 l,r 之間的鏈,使得鏈的總價值和除以鏈長最大 顯然,這個式子的形式讓人想到了01分數規劃。於是根據01分數規劃的套路,先二分乙個答案 考慮如何判斷,現在等於把所有邊都減去了乙個 mid 要看有沒有一條價值大於0的長度介於 l,r 的鏈 是不是感覺點分治呼之...