ABC209F. Deforestation——DP(、数学容斥)
题面
有
n
n
n 棵树排成一排,每棵树高度为
h
i
(
i
∈
[
1
,
n
]
)
h_i~(i\in[1,n])
hi (i∈[1,n]) ,你现在要按照一个排列
P
P
P 的顺序去砍树,每砍一棵树,这棵树的高度就会变成
0
0
0 ,也就是说,砍一棵树
i
i
i 会使得
h
i
→
0
h_i\rightarrow0
hi→0 。由于光头强的阻挠,你每次砍树的代价是当前这棵树相邻两棵树的高度加上这棵树的高度,即
h
i
−
1
+
h
i
+
h
i
+
1
h_{i-1}+h_i+h_{i+1}
hi−1+hi+hi+1 。
求有多少种不同的排列
P
P
P 能保证总代价最小,取模
998
244
353
998\,244\,353
998244353。
1
≤
n
≤
4000
,
1
≤
h
i
≤
1
0
9
1\leq n\leq4000,1\leq h_i\leq10^9
1≤n≤4000,1≤hi≤109 .
题解
我们把排列投射到这一排树上,每个位置记录自己被砍的次序
p
i
p_i
pi 。
那么除了自己被砍时被算进去的代价,额外代价(因砍伐邻居而付出的代价)就可以用
p
p
p 来判断。对于每个
i
∈
[
1
,
n
)
i\in[1,n)
i∈[1,n) ,若
p
i
<
p
i
+
1
p_i<p_{i+1}
pi<pi+1 ,则额外代价加上
h
i
+
1
h_{i+1}
hi+1 ,若
p
i
>
p
i
+
1
p_i>p_{i+1}
pi>pi+1 则额外代价加上
h
i
h_i
hi 。
现在我们看看,该怎么安排
p
i
p_i
pi ,使得总代价最小呢?
对于每个
i
∈
[
1
,
n
)
i\in[1,n)
i∈[1,n) ,如果
h
i
<
h
i
+
1
h_i<h_{i+1}
hi<hi+1 ,那么限制
p
i
>
p
i
+
1
p_i>p_{i+1}
pi>pi+1 ;如果
h
i
>
h
i
+
1
h_i>h_{i+1}
hi>hi+1 ,那么限制
p
i
<
p
i
+
1
p_i<p_{i+1}
pi<pi+1 。如果
h
i
=
h
i
+
1
h_i=h_{i+1}
hi=hi+1 ,相对大小无所谓了,不限制。这样下来,排列
p
p
p 就能使得总代价最小,满足所有限制条件的排列
p
p
p 的个数就是答案了。
那么就是一个经典问题:限制一个排列
p
p
p 相邻两位的大小关系,问总的排列个数。
如果是
n
≤
1
0
5
n\leq10^5
n≤105 级别的数据,要用比较复杂难懂的容斥来做,假定一段同向,然后减去不合法。
可喜(惜)的是,这道题
n
≤
4000
n\leq4000
n≤4000 ,可以
Θ
(
n
2
)
\Theta(n^2)
Θ(n2) 做。我们定义一个简单的
D
P
\rm DP
DP ,令
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示安排到第
i
i
i 位,前面有
j
j
j 个数比
p
i
p_i
pi 小的方案数。转移如下:
- p
i
>
p
i
−
1
p_i>p_{i-1}
pi>pi−1 :
d
p
[
i
]
[
j
]
=
∑
k
=
0
j
−
1
d
p
[
i
−
1
]
[
k
]
dp[i][j]=\sum_{k=0}^{j-1}dp[i-1][k]
dp[i][j]=∑k=0j−1dp[i−1][k]
- p
i
<
p
i
−
1
p_i<p_{i-1}
pi<pi−1 :
d
p
[
i
]
[
j
]
=
∑
k
=
j
i
−
2
d
p
[
i
−
1
]
[
k
]
dp[i][j]=\sum_{k=j}^{i-2}dp[i-1][k]
dp[i][j]=∑k=ji−2dp[i−1][k]
- (
e
m
p
t
y
)
({\rm empty})
(empty) :
d
p
[
i
]
[
j
]
=
∑
k
=
0
i
−
2
d
p
[
i
−
1
]
[
k
]
dp[i][j]=\sum_{k=0}^{i-2}dp[i-1][k]
dp[i][j]=∑k=0i−2dp[i−1][k]
裸的前缀和优化,复杂度
Θ
(
n
2
)
\Theta(n^2)
Θ(n2) 。
CODE
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 4005
#define LL long long
#define DB double
#define lowbit(x) (-(x) & (x))
#define ENDL putchar('\n')
LL read() {
LL f=1,x=0; char s = getchar();
while(s < '0' || s > '9') {if(s == '-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10 + (s-'0');s = getchar();}
return x * f;
}
const int MOD = 1000000007;
int n,m,i,j,s,o,k;
int a[MAXN];
int dp[MAXN][MAXN];
int sum[MAXN][MAXN],suf[MAXN][MAXN];
int main() {
n = read();
for(int i = 1;i <= n;i ++) {
a[i] = read();
}
dp[0][0] = 1;
sum[0][0] = suf[0][0] = 1;
for(int i = 1;i <= n;i ++) {
for(int j = 0;j < i;j ++) {
if(a[i] > a[i-1]) {
dp[i][j] = suf[i-1][j];
}
else if(a[i] < a[i-1]) {
if(j > 0) dp[i][j] = sum[i-1][j-1];
}
else dp[i][j] = suf[i-1][0];
}
sum[i][0] = dp[i][0];
suf[i][i-1] = dp[i][i-1];
for(int j = 1;j < i;j ++) sum[i][j] = (sum[i][j-1] + dp[i][j]) % MOD;
for(int j = i-2;j >= 0;j --) suf[i][j] = (suf[i][j+1] + dp[i][j]) % MOD;
}
int ans = suf[n][0];
printf("%d\n",ans);
return 0;
}
ABC209F. Deforestation——DP(、数学容斥)的更多相关文章
- 青云的机房组网方案(简单+普通+困难)(虚树+树形DP+容斥)
题目链接 1.对于简单的版本n<=500, ai<=50 直接暴力枚举两个点x,y,dfs求x与y的距离. 2.对于普通难度n<=10000,ai<=500 普通难度解法挺多 ...
- bzoj3622已经没有什么好害怕的了 dp+组合+容斥(?)
3622: 已经没有什么好害怕的了 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1033 Solved: 480[Submit][Status][ ...
- [UOJ422][集训队作业2018]小Z的礼物——轮廓线DP+min-max容斥
题目链接: [集训队作业2018]小Z的礼物 题目要求的就是最后一个喜欢的物品的期望得到时间. 根据$min-max$容斥可以知道$E(max(S))=\sum\limits_{T\subseteq ...
- BZOJ4361 isn 树状数组、DP、容斥
传送门 不考虑成为非降序列后停止的限制,那么答案显然是\(\sum\limits_{i=1}^N cnt_i \times (N-i)!\),其中\(cnt_i\)表示长度为\(i\)的非降序列数量 ...
- 洛谷P4859 已经没有什么好害怕的了 [DP,容斥]
传送门 思路 大佬都说这是套路题--嘤嘤嘤我又被吊打了\(Q\omega Q\) 显然,这题是要\(DP\)的. 首先思考一下性质: 为了方便,下面令\(k=\frac{n+k}{2}\),即有恰好\ ...
- CodeForces - 285E: Positions in Permutations(DP+组合数+容斥)
Permutation p is an ordered set of integers p1, p2, ..., pn, consisting of n distinct positive in ...
- 【HDOJ5519】Kykneion asma(状压DP,容斥)
题意:给定n和a[i](i=0..4),求所有n位5进制数中没有前导0且i出现的次数不超过a[i]的数的个数 2<=n<=15000,0<=a[i]<=3e4 思路:设f(n, ...
- loj#2542. 「PKUWC2018」随机游走(树形dp+Min-Max容斥)
传送门 首先,关于\(Min-Max\)容斥 设\(S\)为一个点的集合,每个点的权值为走到这个点的期望时间,则\(Max(S)\)即为走遍这个集合所有点的期望时间,\(Min(S)\)即为第一次走到 ...
- LOJ3102. 「JSOI2019」神经网络 [DP,容斥,生成函数]
传送门 思路 大部分是感性理解,不保证完全正确. 不能算是神仙题,但我还是不会qwq 这题显然就是求:把每一棵树分成若干条链,然后把链拼成一个环,使得相邻的链不来自同一棵树,的方案数.(我才不告诉你们 ...
随机推荐
- Dev C++编写C/C++程序 出现[Error] ld returned 1 exit status报错分析及解决
debug系列第一弹,不知道大家写程序的时候是不是都遇到过如题的报错. 我本人是经常遇到这行熟悉的令人不知所措的报错,可能是我太笨了 有时候百度无果也差不到原因,那就汇总一下目前我遇到的情况吧--持续 ...
- python实现对简单的运算型验证码的识别【不使用OpenCV】
最近在写我们学校的教务系统的手机版,在前端用户执行绑定操作后,服务器将执行登录,但在登录过程中,教务系统中有个运算型的验证码,大致是这个样子的: 下面我们开始实现这个验证码的识别. 1.图片读取 从网 ...
- C语言学习之我见-strcat()字符拼接函数(有缺陷)
strcat()函数,用于两个字符串的拼接. (1)函数原型: char * strcat(char *Dest,const char * Source); (2)头文件: #include < ...
- 隐私计算FATE-模型训练
一.说明 本文分享基于 Fate 自带的测试样例,进行 纵向逻辑回归 算法的模型训练,并且通过 FATE Board 可视化查看结果. 本文的内容为基于 <隐私计算FATE-概念与单机部署指南& ...
- BUUCTF-你竟然赶我走
你竟然赶我走 首先看到这个图片没啥感觉,直接用16进制打开了.拖到最下面果然有flag flag{stego_is_s0_bor1ing}
- 会话技术 Cookie+Session
会话:这种在多次HTTP连接间维护用户与同一用户发出的不同请求之间关联的情况称为维护一个会话(session) 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开: 功能:在一次会话 ...
- NC16539 [NOIP2013]表达式求值
NC16539 [NOIP2013]表达式求值 题目 题目描述 给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值. 输入描述 输入仅有一行,为需要你计算的表达式,表达式中只包含数字.加法运 ...
- C语言输出九九乘法表
C语言学了有一阵子了,趁着假期没事练练手,没想到挺简单 基本思路是这样的 先写一个主函数,然后定义两个变量i1和i2;使用for语句循环嵌套,外层循环负责写循环9次,内循环里面写从1开始递增去和外层循 ...
- SpringBoot接口 - 如何优雅的对接口返回内容统一封装?
在以SpringBoot开发Restful接口时,统一返回方便前端进行开发和封装,以及出现时给出响应编码和信息.@pdai SpringBoot接口 - 如何优雅的对接口返回内容统一封装? RESTf ...
- HDFS、Yarn、Hive…MRS中使用Ranger实现权限管理全栈式实践
摘要:Ranger为组件提供基于PBAC的鉴权插件,供组件服务端运行,目前支持Ranger鉴权的组件有HDFS.Yarn.Hive.HBase.Kafka.Storm和Spark2x,后续会支持更多组 ...