Luogu3352 ZJOI2016 线段树 概率、区间DP
考虑对于每一个位置\(i\),计算所有可能的结果出现的概率。
定义一个区间\([l,r]\)为对于\(x\)的极大区间,当且仅当\(\max \limits _{i=l}^r \{a_i\} \leq x < min\{a_{l-1},a_{r+1}\}\)(其中\(a_0=a_{N+1} = MOD\))
那么我们需要考虑极大区间是如何缩小的。
考虑到设某一个点恰好为\(x\)的方案数转移还需容斥,不妨这么设状态:
设\(f_{x,p,l,r}\)表示已经进行了\(p\)次操作,且区间\([l,r]\)为对于\(x\)的极大区间的方案数。如果初始区间\([l,r]\)是对于\(x\)的极大区间,\(f_{x,0,l,r}=1\),否则为\(0\)。
考虑转移:
①第\(p\)次修改的区间对于\([l,r]\)是否为极大区间没有影响,也就是区间同时位于\([1,l-1]\)或者\([l,r]\)或者\([r+1,N]\),即\(f_{x,p,l,r} += f_{x,p-1,l,r} \times g_{l,r}\),其中\(g_{l,r} = C_l^2 + C_{r-l+2}^2 + C_{N-r+1}^2\)
②第\(p\)次修改的区间的左端点小于\(l\),右端点大于\(r\),这种直接会让\([l,r]\)变为非极大区间,贡献为\(0\)
③第\(p\)次修改的区间有一部分在之前的\([l,r]\),有一部分伸出去,即\(f_{x,p,l,r} += \sum\limits_{j=1}^{l-1} (j-1) \times f_{x,p-1,j,r} + \sum\limits_{j=r+1}^N (N-j) \times f_{x,p-1,l,j}\)
对于③显然是可以前缀和优化的,①中的\(g_{i,j}\)直接预处理,可以做到\(O(N^4)\)的\(DP\)
考虑计算答案,设第\(i\)个点的答案为\(ans_i\),则有\(ans_i = \sum\limits_{j =1}^{max} j \times (\sum\limits_{m=1} ^ i \sum\limits_{p=i}^N f_{j,Q,m,p} - \sum\limits_{m=1} ^ i \sum\limits_{p=i}^N f_{j-1,Q,m,p})\)
其实到这里似乎卡卡常就能过了,因为原题数据随机
但是\(O(N^4)\)过\(400\)未免太假,所以我们需要优化算法
我们把\(ans_i\)的式子拆开
考虑对\(\sum\limits_{m=1} ^ i \sum\limits_{p=i}^N f_{j,Q,m,p}\)进行合并,除了\(j=max\)时前面的系数为\(max\)以外,其他项前面的系数是\(-1\)。也就是说每一个\(\sum\limits_{m=1} ^ i \sum\limits_{p=i}^N f_{j,Q,m,p}\)对答案的贡献为\(-1\)。又考虑到上面\(DP\)的转移式子,\(x\)的值不会影响转移方程,所以我们可以将所有\(x\)的值一起转移
故设\(g_{i,l,r}\)表示进行了\(i\)次操作,区间\([l,r]\)对答案产生的贡献的总和,转移与上面\(f\)的转移是一样的
考虑初始值,对于一个区间\([l,r]\),如果它对于\(x\)是极大区间,则有\(\max \limits _{i=l}^r \{a_i\} \leq x < min\{a_{l-1},a_{r+1}\}\),也就是说合法的\(x\)共有\(min\{a_{l-1},a_{r+1}\}-\max \limits _{i=l}^r \{a_i\}\)个,而每一个\(f\)对答案的贡献为\(-1\),所以\(g_{0,l,r}=-(min\{a_{l-1},a_{r+1}\}-\max \limits _{i=l}^r \{a_i\})\)。
最后考虑一个细节:\(a_0=a_{N+1}=MOD\)。首先很显然地,\([1,N]\)需要是一个极大区间,否则会少算\(x=max\)的情况;然后对于\(f_{max,Q,i,j}\)来说,它的系数在\(ans\)中为\(max\),所以要求\(g_{0,1,N}=max\),也就是\(min\{a_0,a_{N+1}\}=MOD\),所以直接赋值为\(a_0=a_{N+1}=MOD\)即可。
总复杂度\(O(N^3)\),注意需要滚动数组压缩空间
#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = (a << 3) + (a << 1) + (c ^ '0');
c = getchar();
}
return f ? -a : a;
}
const int MOD = 1e9 + 7;
int num[410] , g[410][410] , dp[2][410][410] , C[410][410] , s1[2][410][410] , s2[2][410][410] , N , Q;
void input(){
N = read();
Q = read();
for(int i = 1 ; i <= N ; ++i)
num[i] = read();
num[0] = num[N + 1] = 1e9 + 7;
}
inline int add(int a , int b){
return a + b >= MOD ? a + b - MOD : a + b;
}
inline void calc(int x){
for(int i = 1 ; i <= N ; ++i)
for(int j = 1 ; j <= i ; ++j)
s1[x][j][i] = add(s1[x][j - 1][i] , 1ll * (j - 1) * dp[x][j][i] % MOD);
for(int i = N ; i ; --i)
for(int j = N ; j >= i ; --j)
s2[x][i][j] = add(s2[x][i][j + 1] , 1ll * (N - j) * dp[x][i][j] % MOD);
}
void init(){
for(int i = 1 ; i <= N ; ++i)
for(int j = i ; j <= N ; ++j){
int maxN = 0;
for(int k = i ; k <= j ; ++k)
maxN = max(maxN , num[k]);
if(maxN < min(num[i - 1] , num[j + 1]))
dp[0][i][j] = maxN - min(num[i - 1] , num[j + 1]) + MOD;
}
for(int i = 0 ; i <= N + 1 ; ++i){
C[i][0] = 1;
for(int j = 1 ; j <= i ; ++j)
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
}
for(int i = 1 ; i <= N ; ++i)
for(int j = i ; j <= N ; ++j)
g[i][j] = add(C[i][2] , add(C[N - j + 1][2] , C[j - i + 2][2]));
calc(0);
}
void work(){
for(int i = 1 ; i <= Q ; ++i){
for(int j = 1 ; j <= N ; ++j)
for(int k = j ; k <= N ; ++k)
dp[i & 1][j][k] = (1ll * dp[~i & 1][j][k] * g[j][k] + s1[~i & 1][j - 1][k] + s2[~i & 1][j][k + 1]) % MOD;
calc(i & 1);
}
}
void output(){
for(int i = 1 ; i <= N ; ++i){
int ans = 0;
for(int j = 1 ; j <= i ; ++j)
for(int k = i ; k <= N ; ++k)
ans = (ans + dp[Q & 1][j][k]) % MOD;
cout << ans << ' ';
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in" , "r" , stdin);
//freopen("out" , "w" , stdout);
#endif
input();
init();
work();
output();
return 0;
}
Luogu3352 ZJOI2016 线段树 概率、区间DP的更多相关文章
- 二叉搜索树TREE(线段树,区间DP)
前言 线段树+区间DP题,线段树却不是优化DP的,是不是很意外? 题面 二叉搜索树是一种二叉树,每个节点都有一个权值,并且一个点的权值比其左子树里的点权值都大,比起右子树里的点权值都小. 一种朴素的向 ...
- Codeforces Round #278 (Div. 1) Strip (线段树 二分 RMQ DP)
Strip time limit per test 1 second memory limit per test 256 megabytes input standard input output s ...
- xdoj-1324 (区间离散化-线段树求区间最值)
思想 : 1 优化:题意是覆盖点,将区间看成 (l,r)转化为( l-1,r) 覆盖区间 2 核心:dp[i] 覆盖从1到i区间的最小花费 dp[a[i].r]=min (dp[k])+a[i]s; ...
- Codeforces Round #222 (Div. 1) D. Developing Game 线段树有效区间合并
D. Developing Game Pavel is going to make a game of his dream. However, he knows that he can't mak ...
- hiho一下20周 线段树的区间修改
线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了 ...
- 2016年湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)
原题链接 http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1809 Description Bobo has a balanced parenthes ...
- poj 3468:A Simple Problem with Integers(线段树,区间修改求和)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 58269 ...
- hdu 1556:Color the ball(线段树,区间更新,经典题)
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- hdu 1698:Just a Hook(线段树,区间更新)
Just a Hook Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
随机推荐
- vue axios 与 FormData 结合 提交文件 上传文件
---再利用Vue.axios.FormData做上传文件时,遇到一个问题,后台虽然接收到请求,但是将文件类型识别成了字符串,所以,web端一直报500,结果是自己大意了. 1.因为使用了new F ...
- vs2012碰到生成时报该错误:项目中不存在目标“GatherAllFilesToPublish”
手头一个vs2010升级到vs2012后,web项目发布到本地目录时项目报错:“该项目中不存在目标“GatherAllFilesToPublish”” 通过谷歌大神的帮助,找到了解决方法.共享之. 原 ...
- weblogic系列漏洞整理 -- 1. weblogic安装
目录 0. 概述 1. 下载安装Java环境 2. 下载安装weblogic 安装 部署domain域 进入weblogic 3. 排错 如果出现如下错误 0. 概述 WebLogic是美国Oracl ...
- tkinter中lable标签控件(二)
lable控件 对于tkinter来说,学起来很简单,只要设置好相应的参数即可出结果,所以不用刻意去记住这些参数.学习一遍后理解每个参数的作用是什么即可. 当下次用到的时候来笔记上看一下就行. 内容很 ...
- 通过日志过滤的方法,统计每天内容详情页面的PV数
1.目的: 每天凌晨0点1分统计用户点击进入内容详情页的次数,对内容点击量形成榜单. 2.分析: A./data/log/epg.access.log日志实时打印用户访问页面的日志,并且每天凌晨0点会 ...
- echars关系图
<!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...
- weblogic CVE-2018-2628漏洞利用工具
weblogic CVE-2018-2628漏洞利用 漏洞环境: Windows2018R2 weblogic10.3.6 漏洞利用过程: 搭建好存在CVE-2018-2628漏洞的weblogic平 ...
- Linux运维之如何查看目录被哪些进程所占用,lsof命令、fuser命令
之前将一块硬盘挂载到某个目录下,但是现在我想卸载掉这块硬盘,无论如何都umount不了,有些同学可能说需要加上 -f 参数强制卸载,理论上是可以的,但是在我这里依然不起作用,比如: [root@:vg ...
- Hbase-2.0.0_02_常用操作
主要是常用的hbase shell命令,包括表的创建与删除,表数据的增删查[hbase没有修改]:以及hbase的导出与导入. 参考教程:HBase教程 参考博客:hbase shell基础和常用命令 ...
- oracle数据库用户基本操作
每个数据库都有一系列的用户,为了访问数据库,用户必须使用用户名等信息先连接上数据库实例,oracle数据库提供了多种方式来管理用户安全.创建用户的时候,可以通过授权等操作来限制用户能访问的资源以及一些 ...