競技プログラミング日記

主に AtCoder の記事です

AtCoder Beginner Contest 309E

ABC309E

何代先まで保険に入っているかは,DFSで確認できる. 実行時間に間に合わせるには,DFSの回数を減らすことを考える.

人 \(i\) が複数の保険に入っているとする. \(i\) から \(x\) 代先まで,\(y\) 代先まで保険に入っているとする. このとき,\(i\) 以降は \(max(x,y)\) 代先まで調べれば十分で, \(x,y\) の両方を持っておく必要はない. このため,それぞれの人に対して,複数の保険を一つにまとめることが出来て 1回のDFS で済む.

使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"

int main() {
  ll n, m ;
  cin >> n >> m;
  vvll to(n);
  srep(i,1,n){
    ll p; cin >> p;
    p--;
    to[i].push_back(p);
    to[p].push_back(i);
  }

  vll v(n, -INFL);
  rep(i,m){
    ll x,y; cin >> x >> y;
    x--;
    chmax(v[x], y);
  }

  vll vis(n);
  // vector<bool> b(n);
  auto dfs = [&](auto f, ll cu, ll pa, ll val) -> void {
    if(vis[cu]){
      return ;
    }
    vis[cu] = true;

    ll c_val = max(v[cu], val);
    chmax(v[cu], c_val);

    for(auto ne: to[cu]) if(ne != pa){
      f(f, ne, cu, c_val-1);
    }
  };

  dfs(dfs, 0, -1, v[0]);

  ll ans = 0;
  rep(i,n) if(v[i] >= 0){
    ans ++;
  }
  cout << ans << endl;


  return 0;
}