P2585 [ZJOI2006] 三色二叉树(树形dp

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
typedef vector<int> VI;
const int mod = 1e8;
using ull = unsigned long long;
int n,m;
bool broken[400010];
int a[400010];
int dp[500010][3];
int gp[500010][3];
string s;
int idx =0;
int tree[500010][3];
void build(int root){
    idx++;
    if(s[root] == '0'){
        return;
    }
    if(s[root] == '1'){
        tree[root][0] = idx + 1;
        build(idx + 1);
    }
    if(s[root] == '2'){
        tree[root][0] = idx + 1;
        build(idx + 1);
        tree[root][1] = idx + 1;
        build(idx + 1);
    }
}
void work(int x){
    if(tree[x][1])work(tree[x][1]);
    if(tree[x][0])work(tree[x][0]);
    int l = tree[x][0];
    int r = tree[x][1];
    dp[x][0] = max({dp[l][1]+dp[r][2],dp[r][1]+dp[l][2]}) + 1;
    dp[x][1] = max({dp[l][0]+dp[r][2],dp[r][0]+dp[l][2]});
    dp[x][2] = max({dp[l][0]+dp[r][1],dp[r][0]+dp[l][1]});

    gp[x][0] = min({gp[l][1]+gp[r][2],gp[r][1]+gp[l][2]}) + 1;
    gp[x][1] = min({gp[l][0]+gp[r][2],gp[r][0]+gp[l][2]});
    gp[x][2] = min({gp[l][0]+gp[r][1],gp[r][0]+gp[l][1]});


}

int main(){
    cin>>s;
    s=" "+s;
    build(1);
    //cout<<tree[1][0]<<tree[1][1];
    //cout<<tree[1][1];
    //cout<<idx;
    //memset(gp,0x3f,sizeof gp);
    //memset(dp,0,sizeof gp);
    work(1);


    cout<<max({dp[1][0],dp[1][1],dp[1][2]})<<" ";
    cout<<min({gp[1][0],gp[1][1],gp[1][2]})<<" ";

}

dp[i][x] 第i个节点颜色为x时  绿色的最多数目

gp同理

——————————————————————————————

学会递归建树的操作,其实和tire树是很像的捏,

这题只需要开节点,并不需要在节点中添加值和内容

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值