• 【JZOJ6421】匹配


    description


    analysis

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

    • (0)表示不选择根与某个儿子相连,(1)表示选择根与某个儿子相连,由({iover 2},i-{iover 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
    ",tmp.f[1],tmp.f[0]==tmp.f[1]?(tmp.g[0]+tmp.g[1])%mod:tmp.g[1]);
    	return 0;
    }
    
  • 相关阅读:
    博客
    欧几里得算法的时间复杂度
    Linux伙伴系统1
    伙伴系统
    websocket
    Colored Sticks POJ
    Repository HDU
    Phone List HDU
    Hat’s Words HDU
    HDU1800 字典树写法
  • 原文地址:https://www.cnblogs.com/horizonwd/p/11839883.html
Copyright © 2020-2023  润新知