首页 > 其他 > 详细

【JZOJ6421】匹配

时间:2019-11-12 11:01:06      阅读:72      评论:0      收藏:0      [点我收藏+]

description

技术分享图片


analysis

  • 对于普通树形\(DP\)可以设\(f[i][0/1],g[i][0/1]\)表示\([1,i]\)的线段树的最大值、方案数

  • \(0\)表示不选择根与某个儿子相连,\(1\)表示选择根与某个儿子相连,由\({i\over 2},i-{i\over 2}\)转移得到

  • 转移很不好想,这是\(70pts\)的方法,注意有很多节点信息是不需要知道的

  • 一棵线段树最多只会有\(\log\)个不相同的节点,剩下的可以只搞一次得到

  • 对于\(DP\)的优化,记忆化搜索加哈希就可以记下已经弄过的节点了


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define ha 9260817
#define mod 998244353
#define china 19491001
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)

using namespace std;

ll n,T,now;
struct node{ll x,f[2],g[2];}tmp,hash[ha+5];

inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
    while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline bool judge(ll x)
{
    for (now=x%ha*china%ha;;now=now==ha?0:now+1)
    {
        if (!hash[now].x)return 0;
        if (hash[now].x==x)return 1;
    }
}
inline node dfs(ll x)
{
    if (judge(x))return hash[now];
    ll l=x/2,r=x-l;
    node tmpp,tmpl=dfs(l),tmpr=dfs(r);
    tmpp.x=x,tmpp.f[0]=tmpp.f[1]=tmpp.g[0]=tmpp.g[1]=0;
    fo(j,0,1)fo(k,0,1)
    {
        tmpp.f[0]=max(tmpp.f[0],tmpl.f[j]+tmpr.f[k]);
        if (j!=1 || k!=1)tmpp.f[1]=max(tmpp.f[1],tmpl.f[j]+tmpr.f[k]+1);
    }
    fo(j,0,1)fo(k,0,1)
    {
        if (tmpl.f[j]+tmpr.f[k]==tmpp.f[0])(tmpp.g[0]+=tmpl.g[j]*tmpr.g[k])%=mod;
        if (j!=1 || k!=1)
        {
            ll cnt=(!j && !k?2:1)*tmpl.g[j]*tmpr.g[k]%mod;
            if (tmpl.f[j]+tmpr.f[k]+1==tmpp.f[1])(tmpp.g[1]+=cnt)%=mod;
        }
    }
    for (now=x%ha*china%ha;;now=now==ha?0:now+1)if (!hash[now].x){hash[now]=tmpp;return tmpp;}
}
int main()
{
    freopen("match.in","r",stdin);
    freopen("match.out","w",stdout);
    T=read();
    hash[china%ha].x=1,hash[china%ha].g[0]=1,hash[china%ha].g[1]=0;
    hash[2*china%ha].x=2,hash[2*china%ha].f[1]=1,hash[2*china%ha].g[0]=1,hash[2*china%ha].g[1]=2;
    while (T--)n=read(),tmp=dfs(n),printf("%lld %lld\n",tmp.f[1],tmp.f[0]==tmp.f[1]?(tmp.g[0]+tmp.g[1])%mod:tmp.g[1]);
    return 0;
}

【JZOJ6421】匹配

原文:https://www.cnblogs.com/horizonwd/p/11839883.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!