题解 SP3734 【PERIODNI - Periodni】
考虑用\(DP\)和组合数学来解决。
因为原图像不规则的形状不好处理,所以先用笛卡尔树(性质为小根堆)将其划分成一个一个的矩形。

发现在笛卡尔树上的每个节点都对应一个矩形,矩形高为\(h_x-h_{fa_x}\),宽为\(size_x\)。
结合笛卡尔树的性质,不难得到,红色矩形所对应的节点的两个儿子为绿色矩形和蓝色矩形。

设\(f_{x,i}\)为在节点\(x\)所对应的矩形及其以上的图形中放\(i\)个点的方案数,那么答案为\(f_{root,k}\)
与子树合并时只需枚举在子树图像中放的点个数,再用乘法原理乘起来。
再考虑其本身的矩形。
若是在一个\(n \times m\)的矩形中放\(k\)个点,其方案数为\(C_{n}^kC_{m}^kk!\),因为你需要从\(n\)行中选\(k\)行,从\(m\)列中选\(k\)列,同时这些选择的顺序可以改变,所以再乘上\(k!\)。
那么再考虑本身的矩形时,枚举在自身的矩形中放的点个数,再乘上\(C_{n}^kC_{m}^kk!\)即可
实现细节就看代码吧。
\(code:\)
#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;
}
题解 SP3734 【PERIODNI - Periodni】的更多相关文章
- SP3734 PERIODNI - Periodni
题解: 第一道笛卡尔树dp 会发现以一个点为分界 如果左边大于它右边大于它 那么大于的那部分是相互不影响的 于是我们对序列建立笛卡尔树 满足父亲节点的v<儿子节点的v 然后这棵树的中序遍历为原序 ...
- 【BZOJ2616】SPOJ PERIODNI 笛卡尔树+树形DP
[BZOJ2616]SPOJ PERIODNI Description Input 第1行包括两个正整数N,K,表示了棋盘的列数和放的车数. 第2行包含N个正整数,表示了棋盘每列的高度. Output ...
- [BZOJ2616]SPOJ PERIODNI 树形dp+组合数+逆元
2616: SPOJ PERIODNI Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 128 Solved: 48[Submit][Status][ ...
- spoj periodni
题解: dp 方程弄出来就好做了 代码: #include<bits/stdc++.h> ,M=; typedef int arr[N]; typedef long long ll; in ...
- bzoj 2616 SPOJ PERIODNI——笛卡尔树+树形DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2616 把相同高度的连续一段合成一个位置(可能不需要?),用前缀和维护宽度. 然后每次找区间里 ...
- BZOJ2616 SPOJ PERIODNI(笛卡尔树 + DP)
题意 N,K≤500,h[i]≤106N,K\le 500,h[i]\le10^6N,K≤500,h[i]≤106 题解 建立出小根堆性质的笛卡尔树,于是每个节点可以代表一个矩形,其宽度为子树大小,高 ...
- BZOJ.2616.SPOJ PERIODNI(笛卡尔树 树形DP)
BZOJ SPOJ 直观的想法是构建笛卡尔树(每次取最小值位置划分到两边),在树上DP,这样两个儿子的子树是互不影响的. 令\(f[i][j]\)表示第\(i\)个节点,放了\(j\)个车的方案数. ...
- BZOJ2616 SPOJ PERIODNI(笛卡尔树+树形dp)
考虑建一棵小根堆笛卡尔树,即每次在当前区间中找到最小值,以最小值为界分割区间,由当前最小值所在位置向两边区间最小值所在位置连边,递归建树.那么该笛卡尔树中的一棵子树对应序列的一个连续区间,且根的权值是 ...
- BZOJ2616 : SPOJ PERIODNI
长为$A$,宽为$B$的矩阵放$K$个车的方案数$=C(A,K)\times C(B,K)\times K!$. 建立笛卡尔树,那么左右儿子独立,设$f[i][j]$表示$i$子树内放$j$个车的方案 ...
随机推荐
- Spring系列.SpEL表达式
Spring表达式语言 SpEL语言是一种强大的表达式语言,支持在运行时查询和操作对象.SpEL表达式不一定要创建IOC容器后才能使用.用户完全可以单独调用SpEL的API来独立的使用时SpEL表达式 ...
- DDoS压力测试工具t50
site: https://sourceforge.net/projects/t50/ 例子:t50 192.168.1.1 --flood--protocol T50|TCP|UDP|ICMP--t ...
- 使用docker创建rabbitMQ容器
1.拉去镜像 docker pull rabbitmq:3.7.7-management
- openstack cinder-backup流程与源码分析
在现在的云计算大数据环境下,备份容灾已经变成了一个炙手可热的话题,今天,和大家一起分享一下openstack是怎么做灾备的. [首先介绍快照] snapshot可以为volume创建快照,快照中保存了 ...
- 如何使用SVG及其动画技术为你的 Web 前端开发带来一些新鲜的体验
任何有开发经验的前端工程师都会考虑到不成体系的设备生态所带来的挑战.设备间不同的屏幕尺寸.分辨率和比例使得产品难以提供一致的体验,对于那些对产品有着像素级完美追求的人这种体验差异尤其显著! SVG(可 ...
- 如何写出高性能的CSS3动画
小伙伴们在写CSS3动画时,会发现在手机上很多时候会感到卡顿,然后Google到的解决方案大多是开启GPU加速transform: translate3d(0,0,0); 可解决,但是为什么开启GPU ...
- MySQL 事务 异常 事务隔离的级别
MySQL 事务 异常 事务隔离的级别 事务 在你操作数据库的同时,有可能其他用户还会不断地对数据进行增删改查操作.为了避免并行进行时出现混乱,就产生了"事务".事务就是要保证 ...
- POJ3040贪心
题意:作为创纪录的牛奶生产的奖励,农场主约翰决定开始给Bessie奶牛一个小的每周津贴.FJ有一套硬币N种(1≤N≤20)不同的面额,每枚硬币是所有比他小的硬币面值的倍数,例如1美分硬币.5美分硬币. ...
- JAVA的8种基本数据类型分析
基本数据类型(8个) 1.整数类型(4个) 字节个数 取值范围 byte(字节) 1(8位) -2^7~2^7-1 short(短整型) 2(16位) -2^15~2^15-1 int(整形) 4 ...
- sql-exists、not exists的用法
exists : 强调的是是否返回结果集,不要求知道返回什么, 比如:select name from student where sex = 'm' and mark exists(select 1 ...