zoukankan      html  css  js  c++  java
  • SP3734 PERIODNI Periodni

    考虑到如果只有一个矩形的话我们可以很方便的求出答案。

    那么我们可以通过对序列进行建笛卡尔树来做到划分矩形。

    注意在dp时,子矩阵的合并类似于背包。

    考虑父节点时考虑已经选过的列。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define maxn 5010
    #define mod 1000000007
    template<typename T> inline void read(T &x)
    {
    	x=0;char c=getchar();bool flag=false;
    	while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	if(flag)x=-x;
    }
    ll n,k,top,root;
    ll ls[maxn],rs[maxn],st[maxn];
    ll f[maxn][maxn],h[maxn],siz[maxn],fac[1000050],inv[1000050];
    ll qp(ll x,ll y)
    {
        ll ans=1;
        while(y)
        {
            if(y&1) ans=(ans*x)%mod;
            x=(x*x)%mod;
            y>>=1;
        }
        return ans%mod;
    }
    void init()
    {
        fac[0]=fac[1]=inv[0]=inv[1]=1;
    	fac[2]=2,inv[2]=qp(2,mod-2);
    	for(int i=3;i<=1000000;++i)
    	{
    		fac[i]=(fac[i-1]*i)%mod;
    		inv[i]=qp(fac[i],mod-2);
    	}
    }
    ll C(ll n,ll m)
    {
        if(n<m) return 0;
        return fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
    int build()
    {
        for(int i=1;i<=n;++i)
        {
            while(top&&h[st[top]]>h[i]) ls[i]=st[top--];
            if(top) rs[st[top]]=i;
            st[++top]=i;
        }
        return st[1];
    }
    void dfs(int x,int val)
    {
        f[x][0]=siz[x]=1;
        ll high=h[x]-val;
        if(ls[x])
        {
            ll y=ls[x];
            dfs(y,h[x]),siz[x]+=siz[y];
            for(ll i=min(siz[x],k);i>=0;--i)
                for(ll j=1;j<=min(siz[y],i);++j)
                    f[x][i]=(f[x][i]+f[y][j]*f[x][i-j]%mod)%mod;
        }
        if(rs[x])
        {
            ll y=rs[x];
            dfs(y,h[x]),siz[x]+=siz[y];
            for(ll i=min(siz[x],k);i>=0;--i)
                for(ll j=1;j<=min(siz[y],i);++j)
                    f[x][i]=(f[x][i]+f[y][j]*f[x][i-j]%mod)%mod;
        }
        for(ll i=min(siz[x],k);i>=0;--i)
            for(ll j=1;j<=min(high,i);++j)
                f[x][i]=(f[x][i]+f[x][i-j]*fac[j]%mod*C(high,j)%mod*C(siz[x]-(i-j),j)%mod)%mod;
    }
    int main()
    {
        init();
        read(n),read(k);
        for(int i=1;i<=n;++i) read(h[i]);
        root=build();
        dfs(root,0);
        printf("%lld",f[root][k]);
    	return 0;
    }
    
  • 相关阅读:
    Unix Domain Socket(基于 Linux-2.4.0已更新)
    Eclipse常用设置及部分常用快捷键个人总结(MyEclipse通用)
    使用Docker安装ElasticSearch 以及我遇到的问题
    使用Docker安装MySQL
    es 索引自动删除
    k8s部署zk集群
    k8s-基于Canal来定义网络策略
    Markdown学习
    python ---- Linux压缩某个目录但要跳过指定文件
    WEB前端 ---- 学习第二天(表格、表单、css等)
  • 原文地址:https://www.cnblogs.com/dixiao/p/15093197.html
Copyright © 2011-2022 走看看