bzoj2616
树形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 ;
}
bzoj2616的更多相关文章
- BZOJ2616 SPOJ PERIODNI(笛卡尔树+树形dp)
		
考虑建一棵小根堆笛卡尔树,即每次在当前区间中找到最小值,以最小值为界分割区间,由当前最小值所在位置向两边区间最小值所在位置连边,递归建树.那么该笛卡尔树中的一棵子树对应序列的一个连续区间,且根的权值是 ...
 - 【BZOJ2616】SPOJ PERIODNI 笛卡尔树+树形DP
		
[BZOJ2616]SPOJ PERIODNI Description Input 第1行包括两个正整数N,K,表示了棋盘的列数和放的车数. 第2行包含N个正整数,表示了棋盘每列的高度. Output ...
 - BZOJ2616 : SPOJ PERIODNI
		
长为$A$,宽为$B$的矩阵放$K$个车的方案数$=C(A,K)\times C(B,K)\times K!$. 建立笛卡尔树,那么左右儿子独立,设$f[i][j]$表示$i$子树内放$j$个车的方案 ...
 - bzoj2616: SPOJ PERIODNI——笛卡尔树+DP
		
不连续的处理很麻烦 导致序列DP又找不到优秀的子问题 自底向上考虑? 建立小根堆笛卡尔树 每个点的意义是:高度是(自己-father)的横着的极大矩形 子问题具有递归的优秀性质 f[i][j]i为根子 ...
 - [BZOJ2616]SPOJ PERIODNI  树形dp+组合数+逆元
		
2616: SPOJ PERIODNI Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 128 Solved: 48[Submit][Status][ ...
 - BZOJ2616 SPOJ PERIODNI(笛卡尔树 + DP)
		
题意 N,K≤500,h[i]≤106N,K\le 500,h[i]\le10^6N,K≤500,h[i]≤106 题解 建立出小根堆性质的笛卡尔树,于是每个节点可以代表一个矩形,其宽度为子树大小,高 ...
 - 省选/NOI刷题Day2
		
bzoj2616 放一个车的时候相当于剪掉棋盘的一行,于是就可以转移了,中间状态转移dp套dp,推一下即可 bzoj2878 环套树期望dp 手推一下递推式即可 bzoj3295 树状数组套权值线段树 ...
 
随机推荐
- JDBC自定义连接池
			
开发中,"获得连接"和"释放资源"是非常消耗系统资源的,为了解决此类性能问题可以采用连接池技术来共享连接Connection. 1.概述 用池来管理Connec ...
 - 注解@RequestMapping value 用法
			
本文引自:https://blog.csdn.net/qq_33811662/article/details/80864784 RequestMapping是一个用来处理请求地址映射的注解,可用于类. ...
 - 【Windows7】win7启动 报错 AutoIt错误,不能打开脚本文件
			
解决方法: 1.开始-->运行-->regedit 2.按照下图 3.
 - 实践与理解CMM体系
			
我的项目管理之路--5.实践与理解CMM体系 分类: 管理专辑(65) 过程改进(9) 软件工程(52) 版权声明:本文为博主原创文章,未经博主允许不得转载. 一个现代企业我们可以把它比作为自然界 ...
 - gameplay理解
			
Camera视角:确定显示的视场及视角. Game:显示的基类.静态单例模式.但是获取方式很奇怪. Game::getInstance得到的是__gameInstance,但是__gameInstan ...
 - Missing 'name' key attribute on element activity at AndroidMan
			
<uses-permission android:content="android.permission.CHANGE_WIFI_STATE" /> 这是android ...
 - vs2010配置VL_FEAT库
			
VL_FEAT库是计算机视觉中的一个开源库,支持C/C++,Matlab,可以在http://www.vlfeat.org/下载. 本文主要讲一下VS2010中如何配置vl_feat库(算是对原文的一 ...
 - Eureka vs Zookeeper
			
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性).A(可用性)和P(分区容错性).由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡.在此Zookeeper保证 ...
 - centos 7.xx 安装LAMP环境
			
一.安装Apache 1.安装yum -y install httpd2.开启apache服务systemctl start httpd.service3.设置apache服务开机启动systemct ...
 - ASP.NET MVC判断基于Cookie的Session过期
			
当我们第一次请求访问时,可以看到Response的Set-Cookie里添加了ASP.NET_SessionId的值,以后再访问时可以看到Resquest里的Cookie已经包含这个Key. Se ...