【CodeM初賽B輪】A 貪心
阿新 • • 發佈:2017-06-25
style 排序 但是 cnblogs const 每次 sof pac max
【CodeM初賽B輪】A
題目大意:給你一棵樹,起初所有點都是白色的,你每次都能選擇一個白點i,將這個點i到根路徑上的所有到i的距離<k[i]的點都染成黑色(根和i也算,已經被染成黑色的點還是黑色)。問最少需要染多少次才能將所有點都變黑。
n<=100000
題解:顯然貪心啊,但是我一開始居然寫了樹剖。。。
因為葉子節點是一定要染的,所以我們可以將所有點按DFS序排序,從後往前染。記錄vis[i],表示之前已經將所有到i的距離<=vis[i]的點染成了黑色;再維護mx[i],表示之前染過的點最多能將到i的距離<=mx[i]的點染成黑色。然後用當前的vis和mx去更新fa就行了。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn=100010; int n,cnt,ans; int fa[maxn],tag[maxn],k[maxn],p[maxn],head[maxn],nxt[maxn],to[maxn],ml[maxn]; void add(int a,int b) { to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++; } void dfs(int x) { p[++p[0]]=x; for(int i=head[x];i!=-1;i=nxt[i]) dfs(to[i]); } int main() { scanf("%d",&n); int i,a; memset(head,-1,sizeof(head)); for(i=2;i<=n;i++) scanf("%d",&fa[i]),add(fa[i],i); for(i=1;i<=n;i++) scanf("%d",&k[i]); dfs(1); for(i=n;i>=1;i--) { a=p[i]; ml[a]=max(ml[a],k[a]); if(!tag[a]) tag[a]=ml[a],ans++; ml[fa[a]]=max(ml[fa[a]],ml[a]-1),tag[fa[a]]=max(tag[fa[a]],tag[a]-1); } printf("%d",ans); return 0; }
【CodeM初賽B輪】A 貪心