頹紅警
事實證明,小可愛是最可愛的嚶! ——佚名
現在小可愛在頹遊戲,但是他遇到了一個問題:
小可愛率領的部隊現在面對的是敵軍在這一地區的駐軍,敵國戰爭機器的運作很大程度上依賴指揮,所以敵軍內部是嚴明分級的,就是說,全部敵軍可以看作一棵樹,每隻敵軍部隊(樹上每個節點)有其戰鬥力。你可以對任意敵軍部隊發動進攻,小可愛的部隊有戰鬥力p,意味著他的每次進攻將使得被進攻的這支部隊的戰鬥力減少p,對上級指揮系統的打擊同時會影響其下級部隊。具體來說,當他對點i發動進攻,部隊i的戰力減少p的同時,對於其子樹內點j,部隊j的戰力減少Max(0,p−dis(i,j)2)(dis(i,j)表示點i,j間簡單路徑的長度)。如果某支部隊戰力小於0,那麼這支部隊就被消滅了,一支部隊被消滅不會改變敵軍編制(即這棵樹的結構不會改變)。
小可愛想知道,你的部隊最少發動幾次進攻,才能全殲敵軍
由於小可愛還要爆手速發展自己實力,所以把這個問題交給了你。
小可愛因為太可愛了,所以受到了一些限制——只有在一個部隊的祖先節點都被殲滅之後才能發動進攻去打它,否則它就會被這個部隊的祖先節點攻擊,這是他不願意經歷的。
1. 樹形結構 ‘
2. 只能從上到下進行操作
3. 每個節點值小於0的時候才不可以對其進行操作
4. 1....i - 1中對i會產生影響的,只有令\(p - dis[i , j]^2 > 0\) , 也就是如果用深度表示dis , 那麼就是\(( dis[j] - dis[i] )^2 < p\) , 就是\(dis[j] - dis[i] <\sqrt p\), 也就是說對於i來說它的祖先節點只有距離它\(\sqrt p\)以內的才會對i產生影響。
5. 那麼也就是說對於i來說,我們只關心距離當前點距離為\(\sqrt p\)的點,大於這個的我們都不關心,這個可以用滑動視窗來維護
6. 那麼維護的內容是什麼呢。$$p - dis[i , j] ^ 2 \ = p - (dis(j) - dis(i)) ^ 2 \ = p - dis(i) ^ 2 - dis(j) ^ 2+ 2 * dis(i)*dis(j)$$
可以發現對於一個滑動窗口裡面,\(dis[j]\)
#include <iostream> #include <cstdio> #include <algorithm> #include <unordered_map> #include <vector> #include <map> #include <list> #include <queue> #include <cstring> #include <cstdlib> #include <ctime> #include <cmath> #include <stack> #include <set> #pragma GCC optimize(3 , "Ofast" , "inline") using namespace std ; #define ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0) #define x first #define y second #define ls rt << 1 #define rs rt << 1 | 1 typedef long long ll ; const double esp = 1e-6 , pi = acos(-1) ; typedef pair<int , int> PII ; const int N = 1e6 + 10 , INF = 0x3f3f3f3f , mod = 1e9 + 7; int cinint(){ int t ; scanf("%d" , &t) ; return t ;} int cinll(){ll t ;scanf("%lld" , &t) ;return t ;} ll a[N] , n , p ; vector<int> v[N] ; ll size[N] , size1[N] , size2[N] , len , cnt[N] , res[N] , ans = 0 ; void dfs(int u , int fa , ll d){ if(d > len) { ll t = d - len ; size[u] -= cnt[t] ; size1[u] -= cnt[t] * t ; size2[u] -= cnt[t] * t * t ; } res[u] -= size[u] * (p - d * d) - size2[u] + 2 * size1[u] * d ; ll pos = 0 ; if(res[u] >= 0) pos = res[u] / p + 1 , ans += pos ; cnt[d] = pos ; for(auto x : v[u]) { if(x == fa) continue ; size[x] = size[u] + pos , size1[x] += size1[u] + pos * d , size2[x] += size2[u] + pos * d * d ; dfs(x , u , d + 1) ; } } int work() { n = cinint() , p = cinint() ; len = sqrt(p) + 1 ; for(int i = 1; i <= n ;i ++ ) res[i] = cinint() ; for(int i = 1; i < n ;i ++ ) { int a = cinint() , b = cinint() ; v[a].push_back(b) , v[b].push_back(a) ; } dfs(1 , 0 , 1) ; cout << ans << endl ; return 0 ; } int main() { work() ; return 0 ; } /* */