树形dp+笛卡尔树+单调栈

这道题跟树形dp有什么关系?

事实上,我们对矩形建立笛卡尔树,先找出最矮的矩形,向两边区间最矮的矩形连边,这样就构成了一棵二叉树,因为只有一个矮的区间会对高的区间造成影响,而且儿子之间不会互相影响,并且这样一层一层保证了每段矩形都会被覆盖到,其实就是单调栈,所以这样连是对的,然后跑一个树形背包,dp[i][j]表示i节点子树放了j个车,很明显两个儿子之间不会互相影响,所以自然是可以合并儿子之间的信息。

f[u][i]表示自己不放儿子放的方案数,dp[u][i]表示子树里放i个的方案数,然后转移一下就行了。一个 n*m的矩形内放k个的方案数是k!*C(n,k)*C(m,k),选完行和列的交点后全排列表示所有交点。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = , mod = 1e9 + ;
int n, K, root;
int H[N], h[N], lc[N], rc[N], w[N];
ll dp[N][N], fac[], f[N][N];
void up(ll &x, const ll &t) { x = (x + t) % mod; }
ll power(ll x, ll t)
{
ll ret = ;
for(; t; t >>= , x = x * x % mod) if(t & ) ret = ret * x % mod;
return ret;
}
ll inv(ll x) { return power(x, mod - ); }
ll C(int a, int b)
{
if(a < b) return ;
return fac[a] * inv(fac[b]) % mod * inv(fac[a - b]) % mod;
}
ll calc(int a, int b, int K)
{
if(a < K || b < K) return ;
ll ret = fac[K] * C(a, K) % mod * C(b, K) % mod;
return ret;
}
void dfs(int u)
{
f[u][] = dp[u][] = ;
if(!u) return;
dfs(lc[u]);
dfs(rc[u]);
for(int i = ; i <= K; ++i)
for(int j = ; j <= i; ++j)
up(f[u][i], dp[lc[u]][j] * dp[rc[u]][i - j] % mod);
for(int i = K; i >= ; --i)
for(int j = ; j <= i; ++j) if(f[u][j])
up(dp[u][i], f[u][j] * calc(H[u], w[u] - j, i - j) % mod);
}
int build(int l, int r)
{
if(l > r) return ;
int p = l;
for(int i = l; i <= r; ++i) if(h[i] < h[p]) p = i;
lc[p] = build(l, p - );
rc[p] = build(p + , r);
H[lc[p]] = h[lc[p]] - h[p];
H[rc[p]] = h[rc[p]] - h[p];
w[p] = r - l + ;
return p;
}
int main()
{
scanf("%d%d", &n, &K);
fac[] = ;
for(int i = ; i <= n; ++i) scanf("%d", &h[i]), H[i] = h[i];
for(int i = ; i <= ; ++i) fac[i] = fac[i - ] * (ll)i % mod;
root = build(, n);
dfs(root);
printf("%lld\n", dp[root][K]);
return ;
}

最新文章

  1. HTML ------ 关于表单 Form
  2. Guava学习笔记(1):Optional优雅的使用null
  3. iOS中编写单例类的心得
  4. STM32F4 SPI2初始化及收发数据【使用库函数】
  5. XMLHttpRequest cannot load – Origin is not allowed by Access-Control-Allow-Origin.
  6. SQL行转列汇总
  7. centos下安装php环境
  8. G - Strongly connected - hdu 4635(求连通分量)
  9. 必须声明标量变量 &quot;@cid&quot;。
  10. linq读书笔记3-操作符之select与selectmany
  11. 深度解析Linux通过日志反查入侵
  12. Android:ViewPager扩展的具体解释——导航ViewPagerIndicator(有图片缓存,异步加载图片)
  13. ZOJ 1967 POJ 2570 Fiber Network
  14. Android实现版本更新
  15. vue的增删改查
  16. phpstorm 2017.3.3的安装和破解
  17. PyTorch安装
  18. 使用Keepalived配置主从热备实现Nginx高可用(HA)
  19. Android中弹出dialog后无法捕捉back键
  20. JS 操作数组对象

热门文章

  1. php使用strpos,strstr,strchr注意啦,若是数字查找则会当成ASCII码处理
  2. RED HAT 7 性能监控工具
  3. java zip 工具类
  4. 第二讲_图像数据处理Image Data Processing
  5. 天下文章一大抄 mysql远程连接
  6. time is always a factor, time is always now!!!!
  7. python requests接收chunked编码问题-python源码修改
  8. ng-options bug解决方案(示例)
  9. C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路
  10. 说说怎样管理软件日常执行的server