bzoj2616: SPOJ PERIODNI——笛卡尔树+DP
不连续的处理很麻烦
导致序列DP又找不到优秀的子问题
自底向上考虑?
建立小根堆笛卡尔树
每个点的意义是:高度是(自己-father)的横着的极大矩形
子问题具有递归的优秀性质
f[i][j]i为根子树,放j个
儿子背包合并
考虑本层的矩形放多少个
枚举一共放t个,本层放j个
对于子树里的放置的t-j个,不论怎么放,一定占据了t-j列,剩下W[i]-(t-j)个位置
转移是:
https://blog.csdn.net/qq_39972971/article/details/79359547
当前节点的:枚举放多少个、占哪些行、占哪些列、具体先后顺序。

代码:
C(n,m)时刻注意n>=0&&m>=0&&n>=m否则<0越界还看不出来调死
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define int long long
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=;
const int mod=1e9+;
ll f[N][N];
ll tmp[N];
ll jie[+],inv[+];
int qm(int x,int y){
int ret=;
while(y){
if(y&) ret=(ll)ret*x%mod;
x=(ll)x*x%mod;
y>>=;
}
return ret;
}
int n,k;
int ch[N][],sz[N],fa[N],h[N];
int sta[N],top;
int a[N];
int build(){
top=;
int las=;
for(reg i=;i<=n;++i){
las=;
while(top&&a[i]<a[sta[top]]){
las=sta[top];
--top;
if(top&&a[sta[top]]>a[i]) ch[sta[top]][]=las,fa[las]=sta[top];
else ch[i][]=las,fa[las]=i;
}
sta[++top]=i;
}
while(top>) ch[sta[top-]][]=sta[top],fa[sta[top]]=sta[top-],--top;
return sta[];
}
int C(int n,int m){
if(n<||m<||n<m) return ;
return (ll)jie[n]*inv[m]%mod*inv[n-m]%mod;
}
void dfs(int x){
// cout<<" x ff "<<x<<" "<<ff<<endl;
f[x][]=;
if(!x) return;
sz[x]=;
dfs(ch[x][]);dfs(ch[x][]);
sz[x]+=sz[ch[x][]]+sz[ch[x][]];
h[x]=a[x]-a[fa[x]];
f[x][]=;
for(reg s=;s<=;++s){
if(!ch[x][s]) continue;
int y=ch[x][s];
for(reg j=k;j>=;--j){
for(reg t=;t<=j;++t){
f[x][j]=(f[x][j]+f[x][j-t]*f[y][t])%mod;
}
}
}
for(reg i=k;i>=;--i){
for(reg j=;j<=min(min(i,sz[x]),h[x]);++j){
f[x][i]=(f[x][i]+f[x][i-j]*C(h[x],j)%mod*C(sz[x]-(i-j),j)%mod*jie[j]%mod)%mod;
}
}
}
int main(){
rd(n);rd(k);
int m=;
for(reg i=;i<=n;++i) rd(a[i]),m=max(m,a[i]);
m=max(m,max(n,k));
jie[]=;
for(reg i=;i<=m;++i) jie[i]=(ll)jie[i-]*i%mod;
inv[m]=qm(jie[m],mod-);
for(reg i=m-;i>=;--i) inv[i]=(ll)inv[i+]*(i+)%mod; int rt=build();
// cout<<" rt "<<rt<<endl;
f[][]=;
dfs(rt);
printf("%lld",f[rt][k]);
return ;
} }
signed main(){
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
Miracle::main();
return ;
}
总结:
建出笛卡尔树后有优秀的子问题性质
当前矩形的填法可以归为:先找到几行几列变成子正方形,L行L列的正方形的填法就是L!
bzoj2616: SPOJ PERIODNI——笛卡尔树+DP的更多相关文章
- 【BZOJ2616】SPOJ PERIODNI 笛卡尔树+树形DP
[BZOJ2616]SPOJ PERIODNI Description Input 第1行包括两个正整数N,K,表示了棋盘的列数和放的车数. 第2行包含N个正整数,表示了棋盘每列的高度. Output ...
- BZOJ.2616.SPOJ PERIODNI(笛卡尔树 树形DP)
BZOJ SPOJ 直观的想法是构建笛卡尔树(每次取最小值位置划分到两边),在树上DP,这样两个儿子的子树是互不影响的. 令\(f[i][j]\)表示第\(i\)个节点,放了\(j\)个车的方案数. ...
- 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 题解 建立出小根堆性质的笛卡尔树,于是每个节点可以代表一个矩形,其宽度为子树大小,高 ...
- 洛谷 P5044 - [IOI2018] meetings 会议(笛卡尔树+DP+线段树)
洛谷题面传送门 一道笛卡尔树的 hot tea. 首先我们考虑一个非常 naive 的区间 DP:\(dp_{l,r}\) 表示区间 \([l,r]\) 的答案,那么我们考虑求出 \([l,r]\) ...
- TopCoder 14084 BearPermutations2【笛卡尔树+dp】
传送:https://vjudge.net/problem/TopCoder-14084 只是利用了笛卡尔树的性质,设f[i][j]为区间[i,j]的贡献,然后枚举中间最大的点k来转移,首先是两侧小区 ...
- BZOJ2616 SPOJ PERIODNI(笛卡尔树+树形dp)
考虑建一棵小根堆笛卡尔树,即每次在当前区间中找到最小值,以最小值为界分割区间,由当前最小值所在位置向两边区间最小值所在位置连边,递归建树.那么该笛卡尔树中的一棵子树对应序列的一个连续区间,且根的权值是 ...
- [BZOJ2616]SPOJ PERIODNI 树形dp+组合数+逆元
2616: SPOJ PERIODNI Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 128 Solved: 48[Submit][Status][ ...
- NOIP2011pj表达式的值[树形DP 笛卡尔树 | 栈 表达式解析]
题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × ...
随机推荐
- 20155238 2016-2017-2《Java程序设计》课程总结
每周作业链接汇总(按顺序) 预备作业1 预备作业2 预备作业3 第一周作业 第二周作业 第三周作业 第四周作业 第五周作业 第六周作业 第七周作业 第八周作业 第九周作业 第十周作业 自认为写得最好一 ...
- POJ2274
这真的是一道数据结构的好题. 题意是在一条直线上有n辆车,每辆车有一个初始位置x[i]和速度v[i],问最终(在无限时间后)一共会发生多少次超车事件(mod 1000000),以及输出这些事件(如果大 ...
- 汇编 浮点指令FLD,FSTP,FADD与FPU寄存器
知识点: 浮点数的存放方式 st0至st7 FLD,FST,FADD指令 一.浮点数的存放方式 00401000 /$ 55 PUSH EBP 00401001 |. 8BEC MOV E ...
- 后端自动构建前端css和js
引子: 别的复杂前端开发技术不会,用得多的还是手写代码,手动处理. 3年前手写合并压缩js和css文件的asp脚本代码目前还能正常运行,也就没有多大使用别的技术的动力. 直到近期被一个问题纠结着,今天 ...
- C# 基于泛型的自定义线性节点链表集合示例
本例子实现了如何自定义线性节点集合,具体代码如下: using System; using System.Collections; using System.Collections.Generic; ...
- 01-docker简介
如今Docker的使用已经非常普遍,特别在一线互联网公司.使用Docker技术可以帮助企业快速水平扩展服务,从而到达弹性部署业务的能力.在云服务概念兴起之后,Docker的使用场景和范围进一步发展,如 ...
- git 和 github 链接
第一步 再电脑上安装git 请自行搜索 到你需要的一个目录下:例如/gittest 首先创建文件,然后 git add 和 git commit 不然直接查看 git branch - ...
- 前后端同学必会的Linux基础命令
无论是前端还是后端同学,一些常用的linux命令还是必须要掌握的.发布版本.查看日志等等都会用到.以下是我简单的总结了一些简单又常用的命令,欢迎大家补充.希望能帮助到大家 基础篇 1.进入目录 cd ...
- spark执行在yarn上executor内存不足异常ERROR YarnScheduler: Lost executor 542 on host-bigdata3: Container marked as failed: container_e40_1550646084627_1007653_01_000546 on host: host-bigdata3. Exit status: 143.
当spark跑在yarn上时 单个executor执行时,数据量过大时会导致executor的memory不足而使得rdd 最后lost,最终导致任务执行失败 其中会抛出如图异常信息 如图中异常所示 ...
- Alpha Version Release Of Teamwork: Appendix 1 BUG BASH
在为期一周的发布周中,我们将app本身最后的细节完善,功能代码到位,UI不断改进和优化,团队在开始准备发布之前,对整个APP进行了一次BUG检查,每个人都部署了app在自己的android设备上进行测 ...