題意:給你DFS序和BFS序,求樹的指望高度。c++
解:先分析性質。ide
考慮到BFS序是分層的,DFS序的子樹是一段,那麼咱們遍歷BFS序並在DFS序上標記對應點的話,就會發現BFS序每一層都會把若干棵子樹每一個都分紅若干個小子樹,且換層的時候必定會是DFS序上第一個非空位置。spa
設每一個點的指望深度爲hi,那麼就是要求BFS序最後一個點的h。考慮每一個點的深度怎麼算。若是當前點不是新一層的開頭,那麼它的h必定等於他在BFS序前面一個點的深度。若是是開頭,那麼就要等於它父親的深度 + 1,咱們能夠在DFS序上把每一個點的子樹染色以查明該點的父親。若是這兩種狀況都有可能,那麼h就是這兩種狀況的平均數。code
考慮何時只多是一種狀況。blog
當這個點在DFS序上的位置前於BFS序上前一個點在DFS序上的位置的時候,當前點必定是新一層的開頭。get
當這個點在DFS序上的位置後與BFS序上前一個點在DFS序上的位置的時候:若是這個點和BFS上前一個點在DFS序上的位置不相鄰,那麼這兩個點必定在同一層。it
相鄰的時候,若是當前點在DFS序的前面還有空位,那麼必定在同一層。不然考慮這個子樹後面還有沒有空位,若是有也必定在同一層,由於要換層的話必定要把後面的每一個都走一遍。event
實現的時候就用線段樹維護顏色和區間和。ast
1 #include <bits/stdc++.h> 2 3 const int N = 200010; 4 5 int col[N << 2], sum[N << 2]; 6 int d[N], b[N], pos[N]; 7 double h[N]; 8 9 inline void pushdown(int o) { 10 if(!col[o]) return; 11 col[o << 1] = col[o << 1 | 1] = col[o]; 12 col[o] = 0; 13 return; 14 } 15 16 void add(int p, int l, int r, int o) { 17 if(l == r) { 18 sum[o] = 1; 19 return; 20 } 21 int mid = (l + r) >> 1; 22 if(p <= mid) add(p, l, mid, o << 1); 23 else add(p, mid + 1, r, o << 1 | 1); 24 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 25 return; 26 } 27 28 int getSum(int L, int R, int l, int r, int o) { 29 if(L <= l && r <= R) return sum[o]; 30 int mid = (l + r) >> 1, ans = 0; 31 if(L <= mid) ans += getSum(L, R, l, mid, o << 1); 32 if(mid < R) ans += getSum(L, R, mid + 1, r, o << 1 | 1); 33 return ans; 34 } 35 36 void change(int L, int R, int v, int l, int r, int o) { 37 if(L <= l && r <= R) { 38 col[o] = v; 39 return; 40 } 41 pushdown(o); 42 int mid = (l + r) >> 1; 43 if(L <= mid) change(L, R, v, l, mid, o << 1); 44 if(mid < R) change(L, R, v, mid + 1, r, o << 1 | 1); 45 return; 46 } 47 48 int ask(int p, int l, int r, int o) { 49 if(l == r) return col[o]; 50 int mid = (l + r) >> 1; 51 pushdown(o); 52 if(p <= mid) return ask(p, l, mid, o << 1); 53 else return ask(p, mid + 1, r, o << 1 | 1); 54 } 55 56 int getKth(int k, int l, int r, int o) { 57 if(l == r) { 58 return r + (k > sum[o]); 59 } 60 int mid = (l + r) >> 1; 61 if(k <= sum[o << 1]) { 62 return getKth(k, l, mid, o << 1); 63 } 64 else { 65 return getKth(k - sum[o << 1], mid + 1, r, o << 1 | 1); 66 } 67 } 68 69 int main() { 70 71 int n; 72 scanf("%d", &n); 73 for(int i = 1; i <= n; i++) { 74 scanf("%d", &d[i]); 75 pos[d[i]] = i; 76 } 77 for(int i = 1; i <= n; i++) { 78 scanf("%d", &b[i]); 79 } 80 /// h[1] = 1 81 for(int i = 1; i <= n; i++) { 82 /// b[i] in pos[b[i]] 83 int p = pos[b[i]], lastp = pos[b[i - 1]]; 84 add(p, 1, n, 1); 85 int s = getSum(1, p, 1, n, 1); 86 int ed = getKth(s + 1, 1, n, 1) - 1; 87 /// [p, ed] 88 if(i == 1) { 89 h[b[i]] = 1; 90 } 91 else if(p == lastp + 1 && s == p && (ed < n ? getSum(ed + 1, n, 1, n, 1) : 0) == n - ed) { 92 int fr = ask(p, 1, n, 1); 93 if(fr != d[1]) h[b[i]] = (h[fr] + 1 + h[b[i - 1]]) / 2; 94 else h[b[i]] = h[fr] + 1; 95 } 96 else if(p < lastp) { /// new line 97 int fr = ask(p, 1, n, 1); 98 h[b[i]] = h[fr] + 1; 99 } 100 else { 101 h[b[i]] = h[b[i - 1]]; 102 } 103 change(p, ed, b[i], 1, n, 1); 104 } 105 106 printf("%.3f\n", h[b[n]]); 107 return 0; 108 }