【BZOJ2616】SPOJ PERIODNI

Description

Input

第1行包括两个正整数N,K,表示了棋盘的列数和放的车数。 
第2行包含N个正整数,表示了棋盘每列的高度。

Output

包括一个非负整数,表示有多少种放置的方案,输出答案mod 
1000000007后的结果即可。

Sample Input

5 2
2 3 1 2 4

Sample Output

43

HINT

对于100%的数据,有 N≤500,K≤500,h[i] ≤1000000。

题解:一看题就感觉应该是单调栈什么的。。。具体地说,是笛卡尔树。于是学了一发笛卡尔树的建树方法,感觉跟建虚树差不多。

我们用一个栈来维护笛卡尔树上当前的一条链(向右的链),然后对于第i个点,我们看一下它会被插入到链的哪个位置,这个位置下面的点都连接到i的左儿子处,然后将i入栈。

本题的笛卡尔树要满足每个父亲的高度都比儿子小。

然后考虑树形DP,我们将笛卡尔树上的每个节点看成原图的一个矩形,它的上界是它自己的深度,下界是它父亲的深度,左右边界是它的子树范围。用f[x][y]表示在x的子树中放y个车使其互不影响的方案数。我们只需要考虑x对应的矩形中放多少点以及如何放即可。

用一点组合知识便可得到转移方程,设矩形的长为n,宽为m,当前儿子是a,则:

$f[x][y]=\sum\limits_{b}{f[a][y-b]*f[x][b]}$

再乘上矩形中如何放:

$f[x][z]=\sum\limits_{y}f[x][z-y]*y!C_{n-z+y}^yC_m^y$

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const ll P=1000000007;
int n,m,tot,top,rt;
ll f[510][510],jc[1000010],ine[1000010],jcc[1000010],g[510];
int st[510],fa[510],v[510],ch[510][2];
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
inline ll c(int a,int b)
{
if(a<b) return 0;
return jc[a]*jcc[a-b]%P*jcc[b]%P;
}
int dfs(int x)
{
int a=1,b=v[x]-v[fa[x]],i,j,k,y,aa;
f[x][0]=1;
for(i=0;i<=1;i++) if(ch[x][i])
{
y=ch[x][i],aa=dfs(y);
memset(g,0,sizeof(g));
for(j=0;j<=a;j++) for(k=0;k<=aa&&j+k<=m;k++) g[j+k]=(g[j+k]+f[x][j]*f[y][k])%P;
a+=aa;
for(j=0;j<=a;j++) f[x][j]=g[j];
}
for(i=min(m,a);i>=0;i--)
{
ll tmp=0;
for(j=0;j<=i;j++) tmp=(tmp+f[x][i-j]*jc[j]%P*c(a-i+j,j)%P*c(b,j)%P)%P;
f[x][i]=tmp;
}
return a;
}
int main()
{
n=rd(),m=rd();
int i,a;
for(i=1;i<=n;i++) v[i]=rd();
ine[0]=ine[1]=jc[0]=jc[1]=jcc[0]=jcc[1]=1;
for(i=2;i<=1000000;i++) jc[i]=jc[i-1]*i%P,ine[i]=(P-ine[P%i]*(P/i)%P)%P,jcc[i]=jcc[i-1]*ine[i]%P;
for(i=1;i<=n;i++)
{
while(top&&v[st[top]]>v[i])
{
a=st[top],top--;
if(top&&v[st[top]]>v[i]) ch[st[top]][1]=a,fa[a]=st[top];
else ch[i][0]=a,fa[a]=i;
}
st[++top]=i;
}
while(top>1) ch[st[top-1]][1]=st[top],fa[st[top]]=st[top-1],top--;
rt=st[1],dfs(rt);
printf("%lld",f[rt][m]);
return 0;
}

【BZOJ2616】SPOJ PERIODNI 笛卡尔树+树形DP的更多相关文章

  1. bzoj 2616 SPOJ PERIODNI——笛卡尔树+树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2616 把相同高度的连续一段合成一个位置(可能不需要?),用前缀和维护宽度. 然后每次找区间里 ...

  2. BZOJ.2616.SPOJ PERIODNI(笛卡尔树 树形DP)

    BZOJ SPOJ 直观的想法是构建笛卡尔树(每次取最小值位置划分到两边),在树上DP,这样两个儿子的子树是互不影响的. 令\(f[i][j]\)表示第\(i\)个节点,放了\(j\)个车的方案数. ...

  3. bzoj2616: SPOJ PERIODNI——笛卡尔树+DP

    不连续的处理很麻烦 导致序列DP又找不到优秀的子问题 自底向上考虑? 建立小根堆笛卡尔树 每个点的意义是:高度是(自己-father)的横着的极大矩形 子问题具有递归的优秀性质 f[i][j]i为根子 ...

  4. BZOJ2616 SPOJ PERIODNI(笛卡尔树+树形dp)

    考虑建一棵小根堆笛卡尔树,即每次在当前区间中找到最小值,以最小值为界分割区间,由当前最小值所在位置向两边区间最小值所在位置连边,递归建树.那么该笛卡尔树中的一棵子树对应序列的一个连续区间,且根的权值是 ...

  5. BZOJ2616 SPOJ PERIODNI(笛卡尔树 + DP)

    题意 N,K≤500,h[i]≤106N,K\le 500,h[i]\le10^6N,K≤500,h[i]≤106 题解 建立出小根堆性质的笛卡尔树,于是每个节点可以代表一个矩形,其宽度为子树大小,高 ...

  6. [BZOJ2616]SPOJ PERIODNI 树形dp+组合数+逆元

    2616: SPOJ PERIODNI Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 128  Solved: 48[Submit][Status][ ...

  7. NOIP2011pj表达式的值[树形DP 笛卡尔树 | 栈 表达式解析]

    题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × ...

  8. 洛谷 P5044 - [IOI2018] meetings 会议(笛卡尔树+DP+线段树)

    洛谷题面传送门 一道笛卡尔树的 hot tea. 首先我们考虑一个非常 naive 的区间 DP:\(dp_{l,r}\) 表示区间 \([l,r]\) 的答案,那么我们考虑求出 \([l,r]\) ...

  9. TopCoder 14084 BearPermutations2【笛卡尔树+dp】

    传送:https://vjudge.net/problem/TopCoder-14084 只是利用了笛卡尔树的性质,设f[i][j]为区间[i,j]的贡献,然后枚举中间最大的点k来转移,首先是两侧小区 ...

随机推荐

  1. python--迭代器的实现

    #!/usr/local/python/bin/python3 """ 一个迭代器的例子 """ class exsample(object ...

  2. PHP部分常见算法

    撰于:http://blog.csdn.net/caleng/article/details/5276403

  3. Netty(四):粘包问题描述及解决

    拆包粘包问题解决 netty使用tcp/ip协议传输数据.而tcp/ip协议是类似水流一样的数据传输方式.多次访问的时候有可能出现数据粘包的问题,解决这种问题的方式如下: 1 定长数据流 客户端和服务 ...

  4. Java数据结构和算法(一):简介

    本系列博客我们将学习数据结构和算法,为什么要学习数据结构和算法,这里我举个简单的例子. 编程好比是一辆汽车,而数据结构和算法是汽车内部的变速箱.一个开车的人不懂变速箱的原理也是能开车的,同理一个不懂数 ...

  5. 使用Secure Boot后,导致VMware无法启动虚拟机

    最初安装vmware时就报错  Gtk-Message: Failed to load module "canberra-gtk-module": libcanberra-gtk- ...

  6. atitit.设计文档---操作日志的实现

    atitit.设计文档---操作日志的实现 日志查询 1 ----mybatis  配置... 1 添加日志 1 日志查询 <a class="l-link" href=&q ...

  7. vim手记

    1.normal 模式进入edit模式 i(a,o),进入 command 模式 :,回到normal模式Esc(ctrl+c,ctrl+[)2.help urs_toc 进入帮助文档目录,退出目录: ...

  8. java学习之局部变量以及全局变量

    全局变量 什么是全局变量? 全局变量就好比一个容器或者一个公用的东西一样,就类似外面公共场所的凳子一样,大家都可以使用这个凳子. 和他相反的局部变量是啥子东东呢? 局部变量就是局部的东西,如果全局变量 ...

  9. Mac OS下配置PHP Nginx PHP-FPM

    首先需要安装homebrew, 不赘述了 php-fpm php-fpm是mac下自带的软件, 而且兼容不同的PHP版本, 不用额外安装, 但是fpm是需要配置的, 在/private/etc下有个模 ...

  10. PowerPoint 2010 设置演讲者模式