zoukankan      html  css  js  c++  java
  • D. Serval and Rooted Tree (樹狀DP)

    Codeforce 1153D Serval and Rooted Tree (樹狀DP)

    今天我們來看看CF1153D
    題目連結

    題目
    給一棵數,假設有(k)個葉節點,我們可以給葉節點分配(1)~(k)這些數字,當做這些節點的"值"。
    每個非葉節點的點(不妨令為點(u))的值有可能是所有(u)的子節點的(min)(max)
    令根節點為節點(1),求根節點可能的最大值。

    想法

    首先有可能想到要做樹狀dp,而每個點的狀態就是:「假設點(u)為根的子樹有(k_u)個葉節點,(dp[u])(1)~(k_u)中的最大可能(如果我們給這(k_u)個葉節點分配(1)~(k_u)的值)」。
    如果點(u)(min),那麼我們只要找出(u)的子節點中(dp)值最小的就好。但是如果點(u)(max),那麼要得到(dp[u]),我們只需要在『「(dp)值最大的(u)的子節點(令為(v))」的子樹的葉節點』中分配(k_u)中最大的(k_v)個即可。
    但是如果這樣做,我們會需要維護每一個節點的子樹總共有多少個葉節點。因此我們不妨把(dp)陣列儲存的東西改為:(dp[u])(k_u-)((1)~(k_u)中的最大可能)+1,也就是這次是從(k_u)開始往(1)數,看最大值為第幾個數到的。
    如此一來,(dp)轉移式即可改為:
    (egin{cases} dp[u]=min{dp[v]}_{vin son(u)} ext{if u is max}\ dp[u]=sum_{vin son(u)} dp[v] ext{if u is min} end{cases})
    而最終的答案即為(k-dp[1]+1)

    程式碼:

    const int _n=3e5+10;
    int t,n,s[_n],dpT[_n],k;
    VI G[_n];
    int dp(int v){
      if(dpT[v])return dpT[v];
      if(SZ(G[v])==0){k++;return dpT[v]=1;}
      if(s[v]==1){dpT[v]=dp(G[v][0]);rep(i,1,SZ(G[v]))dpT[v]=min(dpT[v],dp(G[v][i]));}
      if(s[v]==0)rep(i,0,SZ(G[v]))dpT[v]+=dp(G[v][i]);
      return dpT[v];
    }
    main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
      cin>>n;rep(i,1,n+1)cin>>s[i];
      rep(i,2,n+1){cin>>t;G[t].pb(i);}
      dp(1);cout<<k-dp(1)+1<<'
    ';
      return 0;
    }
    

    標頭、模板請點Submission看
    Submission

  • 相关阅读:
    cf492D Vanya and Computer Game
    cf492C Vanya and Exams
    cf492A Vanya and Cubes
    bzoj2038 [2009国家集训队]小Z的袜子(hose)
    bzoj3781 小B的询问
    bzoj1858 [Scoi2010]序列操作
    bzoj1060 [ZJOI2007]时态同步
    算法学习心得
    bzoj1054 [HAOI2008]移动玩具
    bzoj3437 小P的牧场
  • 原文地址:https://www.cnblogs.com/petjelinux/p/13546855.html
Copyright © 2011-2022 走看看