題目鏈結
problem
\(已知有 n 個節點,有 n−1 條邊,形成乙個樹的結構\)。
\(給定乙個根節點 k,每個節點都有乙個權值,節點i的權值為 vi\)
\(給 m 個操作,操作有兩種型別:\)
\(1\space a\space x :表示將節點 a 的權值加上 x\)
\(2\space a :表示求 a 節點的子樹上所有節點的和(包括 a 節點本身)\)
solution
\(有這樣乙個結論:某節點和其所有子樹結點的時間戳dfn是連續的\)
\(我們用乙個dfn時間戳,在進入時為 time1,遍歷完所有子樹結點之後為 time2\)
\(那麼該節點與其所有子樹結點的範圍為乙個連續的time1-time2,這個時候再用樹狀陣列維護即可\)
\(即通過dfn時間戳(dfs序),將樹形轉化為連續線形段\)
#include#define ios ios::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
ll val[maxn];
ll valu[maxn];
vectore[maxn];
int dfn[maxn],ed[maxn];
int cnt;
int n,m,k;
int lowbit(int x)
void add(int x,ll w)
}ll query(int x)
return res;
}void dfs(int p,int fa)
}ed[p] = cnt-1;
}int main()
cnt = 1;
dfs(k,0);
for(int i=1;i<=m;i++)else
}return 0;
}
板子 樹狀陣列
已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數數加上x 2.求出某區間數值和 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含2或4個整數,表示乙個操作,具體如下 操作1 格式 1 ...
樹狀陣列維護區間最值
題目描述 給你乙個1 n的排列和乙個棧,入棧順序給定 你要在不打亂入棧順序的情況下,對陣列進行從大到小排序 當無法完全排序時,請輸出字典序最大的出棧序列 輸入描述 第一行乙個數n 第二行n個數,表示入棧的順序,用空格隔開,結尾無空格 輸出描述 輸出一行n個數表示答案,用空格隔開,結尾無空格 示例1輸...
樹狀陣列維護區間和和區間修改
可以用樹狀陣列在 n logn 內,雖然線段樹也能,但是樹狀陣列的 空間都要比它優越得多.首先我們可以用差分的方法使區間修改可以在log的複雜度完成,但重點在於區間和的查詢.我們知道,此時num i a 1 a 2 a i 可以利用樹狀陣列快速求出.而區間和則是 a 1 a 2 a i a 1 a ...