3252 攻略 dfs序 線段樹

2021-07-09 23:36:46 字數 1374 閱讀 7002

首先維護乙個根到底路徑的字首和,選某個點代表選了此點到根的路徑。

那麼每次選擇了乙個點

x ,這個點所在子樹內的每個點都要減少vx

的收益,那麼對於子樹的區間減可以用df

s −i

nf,代表不可再次選到。

由於每個點只會被刪除一次,而刪除一次的複雜度為o(

logn

) ,所以總的複雜度為o(

nlog

n)。

#include

#include

#define ll long long

#define inf 1e18

using namespace std;

int n,k,cnt,dfn;

ll ans;

ll v[200005],mx[800005],tag[800005];

bool vis[200005];

int pos[200005],in[200005],out[200005],fa[200005],head[200005],list[200005],next[200005],l[800005],r[800005],from[800005];

inline ll read()

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

return a*f;

}inline void insert(int x,int y)

void dfs(int x)

out[x]=dfn;

}inline void update(int k)

inline void pushdown(int k)

void build(int k,int x,int y)

int mid=l[k]+r[k]>>1;

build(k<<1,x,mid); build(k<<1|1,mid+1,y);

update(k);

}void change(int k,int x,int y,ll val)

pushdown(k);

int mid=l[k]+r[k]>>1;

if (y<=mid) change(k<<1,x,y,val);

else

if (x>mid) change(k<<1|1,x,y,val);

else change(k<<1,x,mid,val),change(k<<1|1,mid+1,y,val);

update(k);

}int main()

dfs(1);

build(1,1,n);

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

cout << ans << endl;

return

0;}

BZOJ 3252攻略 dfs序 線段樹

bzoj 3252 攻略 dfs序 線段樹 題目大意 給定一棵以1為根的n個點的樹,樹有點權且點權為正整數,可以選擇k條以根作為起點的路徑,每條路徑的價值即這條路徑上所有點的點權之和。但是選擇一條路徑之後,這條路徑上的所有點的點權會變成0。也就是說,這k條路徑中被重複選擇的點,其點權只能被計算一次 ...

bzoj 3252 攻略 (線段樹 DFS序)

題目大意 選出k條從葉子節點到根節點的路徑,使路徑上的權值之和最大。注意每個點的權值只能被計算一次。看到這道題的第一反應是最大費用最大流。對於每條邊只有第一次流的時候有價值。那麼根據這個思路,我們其實就是每次選取一條權值之和最大的路徑加入答案,因為每個點的權值只能計算一次,所以路徑上的點子樹中所有葉...

Bzoj3252 攻略(dfs序 線段樹)

題目鏈結 可以想到,每次肯定是拿最大價值為最優 考慮改變樹上乙個點的值,只會影響它的子樹,也就是dfs序上的乙個區間,於是可以以dfs序建線段樹,這樣就變成區間問題了 include include define mid int mid l r 1,ls id 1,rs id 1 1 define ...