CF1059E Split the Tree 贪心+倍增

code:

#include <bits/stdc++.h>   
#define N 100004 
#define ll long long  
#define setIO(s) freopen(s".in","r",stdin)     
using namespace std;    
ll S;   
ll val[N],dis[N]; 
int n,len,edges,flag=0; 
int hd[N],to[N],nex[N],up[N],dep[N],fa[19][N],cnt[N],go[N];            
void add(int u,int v) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;    
}    
void dfs(int u,int ff) 
{    
    fa[0][u]=ff; 
    dep[u]=dep[ff]+1; 
    dis[u]=dis[ff]+val[u];          
    for(int i=1;i<19;++i)   fa[i][u]=fa[i-1][fa[i-1][u]];        
    for(int i=hd[u];i;i=nex[i])    dfs(to[i],u);          
} 
void solve(int u) 
{   
    int mx=0;   
    for(int i=hd[u];i;i=nex[i])  solve(to[i]),cnt[u]+=cnt[to[i]],mx=max(mx,go[to[i]]); 
    if(mx==0)   ++cnt[u],go[u]=up[u]; 
    else    go[u]=mx-1;          
}
int main() 
{   
    // setIO("input");     
    int i,j;           
    scanf("%d%d%lld",&n,&len,&S);   
    for(i=1;i<=n;++i)    scanf("%lld",&val[i]);
    for(i=2;i<=n;++i) 
    {
        int x;  
        scanf("%d",&x),add(x,i);     
    }        
    dfs(1,0);     
    for(i=1;i<=n;++i) 
    {      
        int x=i;                                      
        for(j=18;j>=0;--j) if(fa[j][x]&&dep[i]-dep[fa[j][x]]+1<=len&&dis[i]-dis[fa[j][x]]+val[fa[j][x]]<=S)      
                x=fa[j][x];     
        up[i]=dep[i]-dep[x];    // 向上延申最大长度      
        if(val[i]>S)     flag=1;       
    }          
    if(flag)    printf("-1\n"); 
    else    solve(1),printf("%d\n",cnt[1]);  
    return 0; 
}

  

posted @ 2019-11-10 20:27  EM-LGH  阅读(154)  评论(0)    收藏  举报