小h正在玩乙個戰略類遊戲,她可以操縱己方的飛機對敵國的n座城市(編號為1~n)進行轟炸敵國的城市形成了一棵樹,小h會依次進行q次轟炸,每次會選擇乙個城市a進行轟炸,和這座城市距離不超過2的城市都會受損(這裡距離的定義是兩點最短路徑上的邊數),轟炸結束後,小h還想知道當前城市a受損的次數
作為遊戲的開發者之一,你有義務回答小h的問題
第1行,兩個整數n(1≤n≤750000)、q(1≤q≤750000)第2~n行,每行兩個整數表示樹上的一條邊
第n+1~n+q行,每行乙個整數,表示小h這次轟炸的城市
輸出q行,每行乙個整數表示這一次轟炸的城市在此次轟炸後共計受損幾次
輸入設結點x,我們可以知道結點x受到傷害==爺爺造成的傷害+父親+自己+兄弟+兒子+孫子。我們分三步來計算傷害:4 41 2
2 33 412
34輸出1
233
1.爺爺和父親造成的傷害等於在爺爺和父親處投彈的次數,用乙個陣列記錄每個結點投彈次數就可以求出來了。
2.自己和兄弟的傷害,直接求兄弟不好求,我們可以通過父結點受傷來求。用f[fa[x]][1] (fa[x]是x結點的父親)陣列記錄父節點到距離為1的所有子節點造成的傷害,自己和兄弟對自己造成的傷害也就是f[fa[x]][1]的值,每次投彈時f[fa[x]][1]++來維護。
3.兒子和孫子造成的傷害等於兒子和距離為2孫子(孫子找兩次父親)的投彈次數,它是直線傳遞的,只需要用乙個陣列記錄,每次兒子和孫子投彈的時候+1就可以了。
因為不需要遍歷樹,只需要模擬樹形結構,每次向上傳2步值就可以,所以可以不用真的建樹。
#include
using
namespace std;
const
int maxn=
8e5;
int fa[maxn]
,f[maxn][3
],a[maxn]
;int
main()
while
(q--
)else
sum=a[x]
; cout<]+a[fa[fa[x]]]
+sum+f[x][2
]/父親+爺爺+自己和兄弟+孫子和兒子
}return0;
}
牛客演算法周周練2
a 題意 求乙個數的順序和逆序之和。題解 其實就是個閹割版的高精度加法嘛。其實逆序數忽略前導零這個條件是沒有用的,因為順序數不可能有前導零,自然結果也不會有,然後注意下首位進製不取餘。include using namespace std int a 10 b 10 intmain for k j ...
牛客演算法周周練2
題目鏈結 include define sc x scanf lld x define pf printf define rep i,s,e for int i s i e i define dep i,e,s for int i e i s i using namespace std typede...
牛客演算法周練 小H和遊戲(樹上dfs 陣列優化)
題目鏈結 1.題目大意 給出一棵樹,現在如果對乙個節點轟炸一次,那麼和它距離不超過2的節點也會被波及。現在有q q 7e5 次轟炸,問每次被轟炸的後此次轟炸的節點目前為止被轟炸多少次 2.很明顯想到暴力dfs,但是如果只有樹的深度只有2層而且所有子節點均連線在根節點,轟炸q次根節點,時間複雜度達到了...