题目描述

给定一个N列的表格,每列的高度各不相同,但底部对齐,然后向表格中填入K个相同的数,填写时要求不能有两个数在同一列,或同一行,下图中b是错误的填写,a是正确的填写,因为两个a虽然在同一行,但它们中间的表格断开。

输出所有填写方案数对1 000 000 007的余数。

输入:
第一行两个整数 N 和 K (1 ≤ N ≤ 500, 1 ≤ K ≤ 500),表示表格的列数和要填写的数的个数。
接下来一行N个数,表示每列的高度。高度不超过 1 000 000.

输出:
一个整数,方案总数对1000 000 007的余数。

题解

这种问题不好在序列上直接处理,考虑每次从当前序列中找出最小的数作为根,递归构造两边的子树。

这样构造出来的数叫笛卡尔树,保证了中序遍历是原序列,整颗树又满足堆的性质。

因为我们需要的树是静态的,所以构建笛卡尔树的复杂度可以降到O(n),具体构建的方法和虚树基本一致,就用栈维护一下当前的右链就可以了。

每次插入节点时一直弹栈,知道弹不动了,就向左连边,否则就连右边。

然后dp就变得十分容易,设dp[i][j]表示i子树内放j个的方案数,注意:我们每往下递归一层,宽度就要减去h[i],这样方便转移。

答案可能来自三部分,左子树、右子树和自己,转移时讨论一下就好了。

代码

#include<iostream>
#include<cstdio>
#define N 502
using namespace std;
const int mod=1e9+;
typedef long long ll;
const int maxn=;
ll dp[N][N],jie[maxn+],ni[maxn+];
int ch[N][],a[N],n,size[N],k,st[N],top;
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline ll power(ll x,ll y){
ll ans=;
while(y){if(y&)ans=ans*x%mod;x=x*x%mod;y>>=;}
return ans;
}
inline ll C(int n,int m){if(n<m)return ;return jie[n]*ni[m]%mod*ni[n-m]%mod;}
void dfs(int u,int fa){
size[u]=;
if(ch[u][])dfs(ch[u][],u),size[u]+=size[ch[u][]];if(ch[u][])dfs(ch[u][],u),size[u]+=size[ch[u][]];
for(int i=;i<=size[u];++i)
for(int j=;j<=i;++j)(dp[u][i]+=dp[ch[u][]][j]*dp[ch[u][]][i-j]%mod)%=mod;
for(int i=size[u];i>=;--i)
for(int j=;j<i;++j)(dp[u][i]+=dp[u][j]*jie[i-j]%mod*C(size[u]-j,i-j)%mod*C(a[u]-a[fa],i-j)%mod)%=mod;
}
int main(){
n=rd();k=rd();
dp[][]=;
for(int i=;i<=n;++i)a[i]=rd();
jie[]=;
for(int i=;i<=maxn;++i)jie[i]=jie[i-]*i%mod;ni[maxn]=power(jie[maxn],mod-);
for(int i=maxn-;i>=;--i)ni[i]=ni[i+]*(i+)%mod;
for(int i=;i<=n;++i){
while(top&&a[i]<a[st[top]]){
int x=st[top];top--;
if(top&&a[i]<a[st[top]])ch[st[top]][]=x;
else ch[i][]=x;
}
st[++top]=i;
}
while(top>){ch[st[top-]][]=st[top];top--;}
dfs(st[],);
printf("%lld",dp[st[]][k]);
return ; }

BZOJ2616PERIODNI的更多相关文章

随机推荐

  1. uiautomatorviewer 查看元素报错: Error taking device screenshot: null 原因

    使用uiautomatorviewer 查看android某些页面元素,出现错误Error obtaining UI hierarchy  Reason: Error taking device sc ...

  2. 浅谈TCP IP协议栈(一)入门知识【转】

    说来惭愧,打算写关于网络方面的知识很久了,结果到今天才正式动笔,好了,废话不多说,写一些自己能看懂的入门知识,对自己来说是一种知识的总结,也希望能帮到一些想了解网络知识的童鞋. 万事开头难,然后中间难 ...

  3. Failed to initialize component [org.apache.catalina.webresources.JarResource

    去本地仓库里删除掉对应出错的jar包,然后回到pom里面加个空行 让他重新下载(最好把maven仓库全部都删了 重新下载一次 ) 先备份 在复制回来 完美解决

  4. LeetCode算法题-Hamming Distance(Java实现)

    这是悦乐书的第237次更新,第250篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第104题(顺位题号是461).两个整数之间的汉明距离是相应位不同的位置数.给定两个整数 ...

  5. eclipse弃坑记第一篇之在idea上配置Tomcat环境并创建Javaweb项目的详细步骤原创

    IntelliJ IDEA是一款功能强大的开发工具,在代码自动提示.重构.J2EE支持.各类版本工具(如git.svn.github).maven等方面都有很好的应用. IntelliJ IDEA有免 ...

  6. HBase Client JAVA API

    旧 的 HBase 接口逻辑与传统 JDBC 方式很不相同,新的接口与传统 JDBC 的逻辑更加相像,具有更加清晰的 Connection 管理方式. 同时,在旧的接口中,客户端何时将 Put 写到服 ...

  7. hadoop dfs.datanode.du.reserved 预留空间配置方法

    对于datanode配置预留空间的方法 为:在hdfs-site.xml添加如下配置 <property> <name>dfs.datanode.du.reserved< ...

  8. python之面相对象程序设计

    一 面向对象的程序设计的由来 面向对象设计的由来见概述:http://www.cnblogs.com/linhaifeng/articles/6428835.html 面向对象的程序设计:路飞学院版 ...

  9. 高速排序,归并排序,堆排序python实现

    高速排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n^2),平均情况下为O(n*logn),是不稳定的排序 归并排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n*l ...

  10. python字符串replace失效问题

    python字符串replace替换无效 背景 今天想把一个列表中符合条件的元素中 替换部分字符串, 发现怎么替换,改元素还是没有改变,本以为是内存引用的问题后来发现并不然. 经查阅解决 在Pytho ...