nefu 1330 樹上計算 (dfs序+樹狀陣列)
阿新 • • 發佈:2019-01-29
樹上計算
Problem:1330
Time Limit:1000ms
Memory Limit:65535K
Description
給出一棵以 1 為根的樹,初始每個頂點的權值為 0 。 現有兩種操作: 1 x 代表將頂點 x 的權值加一 2 x 詢問頂點 x 的子樹(包含x本身)的權值和是多少
Input
第一行樣例個數 T (T<=10) 對於每組樣例 第一行是一個數 N 代表頂點的個數(1 <= N <= 4e4) 隨後 N - 1 行每行有兩個數 x y 代表頂點 x y 由一條邊相連· 接下來一行是一個數 M 代表操作的次數(1<= M <=4e4) 最後 M 行,每行兩個數 1 x 或 2 x 代表操作(1 <= x <= N)
Output
每次詢問輸出答案,每個答案佔一行。
Sample Input
10 9 1 2 1 3 2 4 2 5 3 6 6 8 6 7 8 9 9 2 1 1 3 2 6 1 6 1 3 2 1 2 8 1 2 2 1 9 1 2 1 3 2 4 2 5 3 6 3 7 6 8 6 9 5 1 6 2 8 1 3 1 4 2 1
Sample Output
0 0 3 0 4 0 3
Hint
Source
DT2131題意:
中文題。
思路:
先用dfs求出他們的dfs序,ls到rs是他們的子樹包括他們自己本身。這樣我們就掌握了每個節點他們的子樹是什麼了。我們只需要一個能單點更新和區間查詢的資料結構就行了。樹狀陣列比較好寫,我們就用樹狀陣列來完成這件事。
程式碼:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn=4e4+500; int ls[maxn],rs[maxn]; vector<int> v[maxn]; int cnt; int tr[maxn]; int lowbit(int i) { return i&(-i); } void update(int i,int n,int c) { while(i<=n) { tr[i]+=c; i+=lowbit(i); } } int query(int n) { int sum=0; while(n>0) { sum+=tr[n]; n-=lowbit(n); } return sum; } void dfs(int now,int fa) { ls[now]=++cnt; for(int i=0;i<v[now].size();i++) { if(v[now][i]==fa) continue; dfs(v[now][i],now); } rs[now]=cnt; } int main() { int t,n,x,y,m,o; scanf("%d",&t); while(t--) { memset(tr,0,sizeof(tr)); scanf("%d",&n); cnt=0; for(int i=1;i<=n;i++) v[i].clear(); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); } dfs(1,0); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&o,&x); if(o==1) { update(ls[x],n,1); } else { printf("%d\n",query(rs[x])-query(ls[x]-1)); } } } return 0; }