【每日一题】4月8日题目精讲 黑白树
試題鏈接
時間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 32768K,其他語言65536K 64bit IO Format:%lld
題目描述
一棵n個點的有根樹,1號點為根,相鄰的兩個節點之間的距離為1。樹上每個節點i對應一個值k[i]。每個點都有一個顏色,初始的時候所有點都是白色的。
你需要通過一系列操作使得最終每個點變成黑色。每次操作需要選擇一個節點i,i必須是白色的,然后i到根的鏈上(包括節點i與根)所有與節點i距離小于k[i]的點都會變黑,已經是黑的點保持為黑。問最少使用幾次操作能把整棵樹變黑。
輸入描述:
第一行一個整數n (1 ≤ n ≤ 105) 接下來n-1行,每行一個整數,依次為2號點到n號點父親的編號。 最后一行n個整數為k[i]
(1 ≤ k[i] ≤ 105)
樣例解釋:
對節點3操作,導致節點2與節點3變黑 對節點4操作,導致節點4變黑 對節點1操作,導致節點1變黑
輸出描述:
一個數表示最少操作次數
示例1
輸入
輸出
3題解:
一開始以為是紅黑樹的姐妹黑白樹。。
求出最少的操作,用dfs
我們要不斷更新染色的最遠距離,還要把子節點的染色范圍更新的父親節點
比如1->2->3-.>4->5->6->7
f[2]=5,f[3]=2
2節點就可以直接染色到6
操作完2之后,如果3就已經被染色了,如果3能染色的范圍比fa[ 2 ]-1(因為2已經染色了本身,所以減一)還大,那染色范圍可以更遠
如果fa[3]<fa[2]-1,就把f3的最遠距離更新到fa[2]-1
總結就是fa[fa]=max( fa [ fa ] , fa [ son ] - 1 )
因為染色都是從下向上的。如果一個節點沒辦法被它子樹的節點染色,那這個節點的父親節點也沒辦法將它染色,他只能自己染色了
代碼:
#include<bits/stdc++.h> #define forr(n) for(int i=1;i<=n;i++) using namespace std; const int maxn=100004; int fa[maxn]; int sum; vector<int>w[maxn]; int a[maxn]; void dfs(int x) {for(int j=0;j<w[x].size();j++){dfs(w[x][j]);fa[x]=max( fa[ w[x][j] ]-1 , fa[x] );a[x]=max( a[ w[x][j] ]-1 , a[x] );}if(fa[x]==0){sum++;fa[x]=a[x];}} int main() {int n,m;cin>>n;forr(n-1){cin>>m;w[m].push_back(i+1);}forr(n){cin>>a[i];}dfs(1);cout<<sum;return 0;}總結
以上是生活随笔為你收集整理的【每日一题】4月8日题目精讲 黑白树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android byteBuffer的使
- 下一篇: 身体训练