-
题目大意 :给出一棵树,节点有点权,求每个节点的祖先中点权小于该节点的结点的个数 。
-
思路如下 :
-
从根节点开始,对树进行深度优先遍历。
- 当进行到节点 i 时,有:
-
$ ext{i}$ 的祖先们 $ ext{Father[i]}$ 已经被访问过了,但还没有退出。
-
其他节点或者已经被访问过并退出了,或者还没有被访问。
-
-
那么需要一个数据结构,维护那些已经被访问过了,但还没有退出的点权,支持查询小于特定值的元素的数量 。
-
可以使用树状数组或者线段树。
-
-
Code
-
#include <cstdio> #include <cstring> #define re register #define GC getchar() #define Clean(X,K) memset(X,K,sizeof(X)) #define Lowbit(X) (X&(-X)) int Qread () { int X = 0 ; char C = GC ; while (C > '9' || C < '0') C = GC ; while (C >='0' && C <='9') { X = X * 10 + C - '0' ; C = GC ; } return X ; } const int Maxn = 100005 ; int N , P_C[Maxn] , Ans[Maxn] , En = 0 , Head[Maxn] , T[Maxn]; struct Edge { int From_Where , Goto_Where , Next_Edge ; }; Edge E[Maxn * 2] ; void Adg (int X , int Y) { E[++En].From_Where = X ; E[En].Goto_Where = Y ; E[En].Next_Edge = Head[X] ; Head[X] = En ; } void Add (int X , int K) { while (X <= N) { T[X] += K ; X += Lowbit(X) ; } } int Ask (int X) { int Ans = 0 ; while (X > 0) { Ans += T[X] ; X -= Lowbit(X) ; } return Ans ; } void Super_Powerful_DFS (int X , int Lst) { Ans[P_C[X]] = Ask (P_C[X]) ; //printf ("%d %d %d " , X , P_C[X],Ans[P_C[X]]) ; Add (P_C[X] , 1) ; for (re int i = Head[X] ; i ; i = E[i].Next_Edge ) { if (E[i].Goto_Where == Lst) continue ; Super_Powerful_DFS ( E[i].Goto_Where , X) ; } Add (P_C[X] , -1) ; } int main () { //freopen ("P2982.in" , "r" , stdin) ; Clean (Ans , 0) , Clean (Head , 0) , Clean (T , 0) , En = 0 ; N = Qread () ; for (re int i = 1 ; i < N ; ++ i) { int X = Qread () , Y = Qread () ; Adg (X , Y) , Adg (Y , X) ; } for (re int i = 1 ; i <= N; ++ i) { int X = Qread () ; P_C[X] = i ; } Super_Powerful_DFS ( 1 , -1) ; for (re int i = 1 ; i <= N; ++ i) printf ("%d " , Ans[i]) ; fclose (stdin) ; fclose (stdout); return 0; }