YbtOJ 763 攻城略池 線段樹合併

2021-10-19 17:32:00 字數 1599 閱讀 3198

給出n

nn個點的一棵樹,每個di=

0d_i=0

di​=

0的點每秒會產生乙個士兵往根節點走,走到乙個節點讓乙個節點d

id_i

di​減一(為0

00就不管)。

求需要多久才能讓所有點的d

dd值變為000

1 ≤n

≤105

,1≤d

i≤10

81\leq n\leq10^5,1\leq d_i\leq 10^8

1≤n≤10

5,1≤

di​≤

108考慮求出每個點d

id_i

di​值變成0

00的時間t

it_i

ti​。

對於乙個節點x

xx,dis

xdis_x

disx

​表示根節點到x

xx的距離,那麼它在時刻t

tt時的減少數量是

∑ y∈

subt

reex

ma

x\sum_max\

y∈subt

reex

​∑​m

ax我們可以每次把新得到的ty−

disy

t_y-dis_y

ty​−di

sy​時間複雜度o(n

log⁡n)

o(n\log n)

o(nlogn)

#include

#include

#include

#define ll long long

using

namespace std;

const ll n=

1e5+

10,inf=

2e8;

struct nodea[n<<1]

;ll n,tot,cnt,ans,ls[n]

,d[n]

,t[n]

,rt[n]

,dep[n]

;void

addl

(ll x,ll y,ll w)

struct segtree

ll ask

(ll x,ll l,ll r,ll k,ll zc,ll zw)

ll merge

(ll x,ll y,ll l,ll r)

}t;void

dfs(ll x,ll fa)

t[x]

=max

(0ll

,t.ask

(rt[x],0

,inf,d[x],0

,0)-dep[x]);

t.change

(rt[x],0

,inf,t[x]

+dep[x]);

ans=

max(ans,t[x]);

return;}

signed

main()

dfs(1,

1);printf

("%lld\n"

,ans)

;return0;

}

YbtOJ 763 攻城略池

設 f x 是點 x 被攻占的時間。顯然這個值可以二分,然後枚舉子樹內的每乙個點,計算在二分到的時間內從列舉到的點可以過去多少人。在 mid 時間內會被攻占當且僅當 d x leq sum x max mid f y text y text x 0 c times mid v 然後往上的時候線段樹合...

YbtOJ 763 攻城略池 線段樹合併

給出 n 個點的一棵樹,每個 d i 0 的點每秒會產生乙個士兵往根節點走,走到乙個節點讓乙個節點 d i 減一 為 0 就不管 求需要多久才能讓所有點的 d 值變為 0 1 leq n leq10 5,1 leq d i leq 10 8 考慮求出每個點 d i 值變成 0 的時間 t i 對於乙...

雷達裝置 Ybtoj

有n nn個建築物,第i ii個建築物在笛卡爾座標系上的座標為 xi yi x i,y i xi y i 你需要在x xx軸上安裝一些雷達,每個雷達的偵察半徑均為d dd,要求每個建築物都至少被乙個雷達偵測到,求最少要安裝幾個雷達。第一行兩個正整數n,d n,dn,d。接下來n nn行,第i ii行...