題意:
已知有n個節點,有n−1條邊,形成乙個樹的結構。
給定乙個根節點k,每個節點都有乙個權值,節點i的權值為vi。
給m個操作,操作有兩種型別:
1 a x :表示將節點a的權值加上x
2 a :表示求a節點的子樹上所有節點的和(包括a節點本身)
題解:
dfs序+線段樹
用dfs序確定in[x]和out[x]的位置,in是當前結點開始的時間戳,out是回溯到當前結點的時間戳,當查詢某結點時,可以快速確定他子樹的範圍。
**:
/*keep on going never give up*/
//#pragma gcc optimize(3,"ofast","inline")
#include
//#define int long long
#define endl '\n'
#define accepted 0
#define ak main()
#define i_can signed
using
namespace std;
const
int maxn =
1e6+10;
const
int maxn =
0x3f3f3f3f
;const
int minn =
0xc0c0c00c
;typedef
long
long ll;
const
int inf=
0x3f3f3f3f
;const ll mod=
1e9+7;
vector<
int> edge[maxn]
;int a[maxn]
;int in[maxn]
,out[maxn]
,id[maxn]
,cnt;
int tree[maxn<<2]
;void
dfs(
int u,
int fa)
out[u]
=cnt;
}void
build
(int node,
int l,
int r)
int mid=
(l+r)/2
;build(2
*node,l,mid)
;build(2
*node+
1,mid+
1,r)
; tree[node]
=tree[
2*node]
+tree[
2*node+1]
;}void
update
(int node,
int l,
int r,
int pos,
int val)
int mid=
(l+r)/2
;if(pos<=mid)
update
(node*
2,l,mid,pos,val)
;else
update
(node*2+
1,mid+
1,r,pos,val)
; tree[node]
=tree[node*2]
+tree[node*2+
1];}
intquery
(int node,
int l,
int r,
int start,
int ends)
int ans=0;
int mid=
(l+r)/2
;if(start<=mid) ans+
=query
(node*
2,l,mid,start,ends);if
(ends>mid) ans+
=query
(node*2+
1,mid+
1,r,start,ends)
;return ans;
}int
main()
dfs(root,-1
);//for(int i=1;i<=n;i++) cout,1
,n);
for(
int i=
0;i)else
}return0;
}
樹上求和( dfs序 線段樹 )
題目鏈結 解題報告 將樹轉化成dfs序,對於任意節點及其子樹總是一段連續的區間,那麼轉化成區間問題。ai b 2 ai ai 2 ai b b b 很明顯線段樹維護即可。define first f define second s define ll long long define mp make...
dfs序 線段樹
傳送門 現有一棵樹,有以下操作 1.節點x及其所有子孫顏色都變更為k。2.要求你回答節點x的顏色。初始所有點都沒有染色。input 第一行乙個整數t t 10 表示樣例組數。對於每個測試樣例 第一行乙個整數n n 5e4 表示樹的節點個數。接下來n行,每行兩個整數u,v 1 u,v n 表示樹中u的...
nefu 1330 樹上求和dfs序 線段樹
dfs序即先序遍歷樹,對於第乙個節點進行總結點個數加一並且賦值操作。思路 對於給出的點,進行vecter建樹。建樹完成後dfs序求出各節點,dfs序,ls i 表示當前節點的dfs序為多少,rs i 表示以當前節點為根的子樹的最右邊節點值。include include include includ...