【每日一题】黑白树(思维+dfs)
黑白树
https://ac.nowcoder.com/acm/problem/13249
Solution
emm昨天看了但是没有写出来,因为不会处理回溯过程中的更有利涂黑的情况。
题解很巧妙,没想到可以用另外一个数组d来记录可以最多涂黑到哪个点,当数组d为0时就代表需要多操作一次,而这个更新操作次数正是这道题的灵魂所在。
简单来说就是:
更新回溯过程中最远可到达的距离
更新回溯过程中无须操作就可到达的距离
而当为0时就代表需要多花一次操作次数。
Code
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define inf 0x3f3f3f3f #define mod 1000000007 #define pb push_back #define mp make_pair #define fi first #define se second #define lowbit(x) (x&(-x)) using namespace std; inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;} void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); } ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a = (a*a)%p;b >>= 1;}return ans%p;} const ull base=2333; const ull pp=19260811; const ull ppp=999998639; const int manx=1e5+5; const int mo=998244353; vector<ll>g[manx]; ll w[manx],d[manx]; ll ans=0; void dfs(ll u,ll pre){ for(auto v:g[u]){ if(v==pre) continue; dfs(v,u); w[u]=max(w[u],w[v]-1); d[u]=max(d[u],d[v]-1); } if(!d[u]) ++ans,d[u]=w[u]; } int main(){ ll n=read(); for(int i=2;i<=n;i++){ ll f=read(); g[f].pb(i); } for(int i=1;i<=n;i++) w[i]=read(); dfs(1,0); printf("%lld",ans); return 0; }