首先維護乙個根到底路徑的字首和,選某個點代表選了此點到根的路徑。
那麼每次選擇了乙個點
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 ...