zoukankan      html  css  js  c++  java
  • 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]);
    }
  • 相关阅读:
    PHP框架 CI与TP之MVC比较
    多线程设计要点
    BigPipe 的工作原理
    Linux yum命令的使用技巧
    java 乱码问题
    win7或xp下常用命令
    不同场景下JVM参数的设置
    win7笔记本创建wifi热点
    maven编译出现Java heap space
    Curling 2.0——蛋疼的一道题
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8148895.html
Copyright © 2011-2022 走看看