bzoj 3252 攻略 (線段樹 DFS序)

2021-08-02 09:32:23 字數 1317 閱讀 8158

題目大意:選出k條從葉子節點到根節點的路徑,使路徑上的權值之和最大。注意每個點的權值只能被計算一次。

看到這道題的第一反應是最大費用最大流。對於每條邊只有第一次流的時候有價值。

那麼根據這個思路,我們其實就是每次選取一條權值之和最大的路徑加入答案,因為每個點的權值只能計算一次,所以路徑上的點子樹中所有葉子幾點都要減去這個點的價值,就是用線段樹維護每個點到根的距離。

按照只有葉子節點的dfs序建樹,這樣每次修改就是連續區間了。

#include#include#include#include#include#define ll long long 

#define n 400003

using namespace std;

int tot,nxt[n],point[n],v[n],pos[n],l[n],r[n],pd[n],mark[n],sz,n,m,fa[n];

ll tr[n*4],val[n],sum[n],delta[n];

void add(int x,int y)

void dfs(int x,int f)

if (!pd)

l[x]=sz+1;

for (int i=point[x];i;i=nxt[i])

r[x]=sz;

}void update(int

now)

void build(int

now,int l,int r)

intmid=(l+r)/2;

build(now

<<1,l,mid);

build(now

<<1|1,mid+1,r);

update(now);

}void pushdown(int

now)

}void query(int

now,int l,int r,int ll,int rr,ll v)

intmid=(l+r)/2;

pushdown(now);

if (ll<=mid) query(now

<<1,l,mid,ll,rr,v);

if (rr>mid) query(now

<<1|1,mid+1,r,ll,rr,v);

update(now);

}void solve(int x)

}int main()

dfs(1,0);

build(1,1,sz);

ll ans=0;

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

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

}

BZOJ 3252攻略 dfs序 線段樹

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

Bzoj3252 攻略(dfs序 線段樹)

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

bzoj3252攻略 線段樹 dfs序

time limit 10 sec memory limit 128 mb submit 562 solved 238 submit status discuss 題目簡述 樹版 k取方格數 眾所周知,桂木桂馬是攻略之神,開啟攻略之神模式後,他可以同時攻略k部遊戲。今天他得到了一款新遊戲 xx半島 ...