zoukankan      html  css  js  c++  java
  • SP3734 PERIODNI

    题意:

    戳这里

    分析:

    一看到是直方图的题目,我们可以联想到笛卡尔树

    我们将列数作为 BST 的一维,将高度作为小根堆的一维,这样笛卡尔树上每一个节点都是一个矩形

    我们考虑在矩形中选出 k 个合法点的方案数,显然等价于 (C_{wid}^kC_{hig}^kk!) ,表示选出 k 种高度和下标并配对,且点之间有标号

    然后我们在笛卡尔树上DP,设 (f_{i,j}) 表示节点 (i) 所代表的子树内选了 (j) 个点的方案,转移方程如下:

    [egin{cases} f_{u,i}=f_{u,i}+f_{v,j}*f_{u,i-j} (子树向父亲贡献) \ f_{u,i}=f_{u,i}+f_{u,i-j}*C_{siz-(i-j)}^jC_{hig}^j*j!(选择自己代表的矩形) end{cases} ]

    代码:

    #include<bits/stdc++.h>
    #define inl inline
    #define reg register
    
    using namespace std;
    
    namespace zzc
    {
        typedef long long ll;
        inl ll read()
        {
            ll x=0,f=1;char ch=getchar();
            while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
            while(isdigit(ch)) {x=x*10+ch-48;ch=getchar();}
            return x*f;
        }
    
        const ll mod = 1e9+7;
        const ll maxn = 505;
        const ll maxm = 1e6+5;
        ll n,k,top;
        ll ch[maxn][2],a[maxn],st[maxn],f[maxn][maxn],fac[maxm],inv[maxm],wid[maxn],siz[maxn];
    
        void init()
        {
            fac[0]=fac[1]=1;
            inv[0]=inv[1]=1;
            for(reg ll i=2;i<=1000000;i++) fac[i]=fac[i-1]*i%mod,inv[i]=inv[mod%i]*(mod-mod/i)%mod;
            for(reg ll i=2;i<=1000000;i++) inv[i]=inv[i]*inv[i-1]%mod;
        }
    
        ll C(ll n,ll m)
        {
            if(n<m) return 0;
            return fac[n]*inv[n-m]%mod*inv[m]%mod;
        }
    
        void dfs(ll u,ll hig)
        {
            hig=a[u]-hig;
            f[u][0]=1;siz[u]=1;
            for(reg ll t=0;t<=1;t++)
            {
                if(!ch[u][t]) continue;
                dfs(ch[u][t],a[u]);
                siz[u]+=siz[ch[u][t]];
                for(reg ll i=min(siz[u],k);i>=0;i--) 
                    for(reg ll j=1;j<=min(siz[ch[u][t]],i);j++) 
                        f[u][i]=(f[u][i]+f[u][i-j]*f[ch[u][t]][j]%mod)%mod;
            }
            for(reg ll i=min(siz[u],k);i>=0;i--)
                for(reg ll j=1;j<=min(hig,i);j++)
                    f[u][i]=(f[u][i]+f[u][i-j]*C(siz[u]-(i-j),j)%mod*C(hig,j)%mod*fac[j]%mod)%mod;
        }
    
        void work()
        {
            init();
            n=read();k=read();
            for(reg ll i=1;i<=n;i++) a[i]=read();
            for(reg ll i=1;i<=n;i++)
            {
                ll j=top;
                while(j&&a[st[j]]>a[i]) j--;
                if(j) ch[st[j]][1]=i;
                if(j<top) ch[i][0]=st[j+1];
                top=j;st[++top]=i;
            }
            dfs(st[1],0);
            printf("%lld
    ",f[st[1]][k]);
        }
    }
    
    int main()
    {
        zzc::work();
        return 0;
    }
    
  • 相关阅读:
    Android Training精要(二)開啟ActionBar的Overlay模式
    Android Training精要(一)ActionBar上级菜单导航图标
    SimpleDateFormat的线程安全问题
    svn删除目录后提交显示Item 'XXXX' is out of date解决方法
    使用 python 开发 Web Service
    Bootstrap 中文文档教程
    起步 简介整个项目、组件、和如何使用一个简单的模版入门
    mysql笔记——索引
    20个数据库设计的最佳实践
    ASP.NET MVC Bootstrap极速开发框架
  • 原文地址:https://www.cnblogs.com/youth518/p/14485171.html
Copyright © 2011-2022 走看看