• bzoj5123: 线段树的匹配


    http://www.lydsy.com/JudgeOnline/upload/201712/prob12.pdf

    dp[len][0/1] 表示节点表示区间长度为len,节点选/不选的 最大匹配

    sum[len][0/1] 表示对应dp[len][0/1]的方案数

    这里选节点即选节点与其父节点的边

    设区间长度为len,左子区间长度为L,右子区间长度为R

    这个节点选,那么左右子节点都不能选

    dp[len][1]=1+dp[L][0]+dp[R][0]

    sum[len][1]=sum[L][0]*sum[R][0]

    这个节点不选,有3种情况:

    左右子节点都不选:

    dp[len][0]=dp[L][0]+dp[R][0]

    sum[len][0]=sum[L][0]+sum[R][0]

    选左子节点:

    dp[len][0]=dp[L][1]+dp[R][0]

    sum[len][0]=sum[L][1]+sum[R][0]

    选右子节点:

    dp[len][0]=dp[L][0]+dp[R][1]

    sum[len][0]=sum[L][0]+sum[R][1]

    如果dp[len][0] 在三种情况中有相同的,sum[len][0]要累加

    len虽然是1e18,但只会用log种,所以用map

    #include<map>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    typedef long long LL;
    
    const int mod=998244353;
    
    //int dp[100001][2];
    //int sum[10001][2];
    
    map<LL,LL>dp[2];
    map<LL,LL>sum[2];
    
    void dfs(LL len)
    {
        if(len==1)
        {
            dp[0][1]=0;
            sum[0][1]=1;
            dp[1][1]=1;
            sum[1][1]=1;
            return;
        }
        LL R=len>>1;
        LL L=len-R;
        if(dp[0].find(L)==dp[0].end()) dfs(L);
        if(dp[0].find(R)==dp[0].end()) dfs(R);
        dp[1][len]=1+dp[0][L]+dp[0][R];
        sum[1][len]=sum[0][L]*sum[0][R]%mod;
        dp[0][len]=dp[1][len]-1;
        sum[0][len]=sum[1][len];
        if(dp[0][L]+dp[1][R]>dp[0][len])
        {
            dp[0][len]=dp[0][L]+dp[1][R];
            sum[0][len]=sum[0][L]*sum[1][R]%mod;
        }
        else if(dp[0][L]+dp[1][R]==dp[0][len])
        {
            sum[0][len]=(sum[0][len]+sum[0][L]*sum[1][R])%mod;
        }
        if(dp[1][L]+dp[0][R]>dp[0][len])
        {
            dp[0][len]=dp[1][L]+dp[0][R];
            sum[0][len]=sum[1][L]*sum[0][R]%mod;
        }
        else if(dp[1][L]+dp[0][R]==dp[0][len])
        {
            sum[0][len]=(sum[0][len]+sum[1][L]*sum[0][R])%mod;
        }
    }
    
    int main()
    {
        LL n;
        scanf("%I64d",&n);
        dfs(n);
        printf("%I64d %I64d",dp[0][n],sum[0][n]);
    }
  • 相关阅读:
    Python日期与时间
    Python文章导航
    Python Tuple元组的操作说明
    Python List列表的操作说明
    Python数字类型及数学运算
    用Python实现一个简单的猜数字游戏
    Python基础语法
    设计模式的六大原则
    设计模式
    设计模式
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8148895.html
Copyright © 2020-2023  润新知