BZOJ4574 [Zjoi2016]线段树
比较厉害的dp.
网上题解都是利用了随机的条件,用了一个$O(n^4)$的dp,这里简单说一下。
用f(x,i,l,r)表示经过前i轮操作,[l,r]的所有数<=x,且l-1和r+1都>x的方案数。
转移:f(x,i,l,r)=f(x,i-1,l,r)*g(l,r)+f(x,i-1,j,r)*(j-1)+f(x,i-1,l,k)*(n-k),j<l,k>r
其中,g(l,r)=l*(l-1)/2+(r-l+1)*(r-l+2)/2+(n-r)*(n-r+1)/2
用个前缀和优化一下转移即可。
设h(x,i)表示最终位置i的数<=x的方案数,h(x,i)=$\sum_{l=1}^i\sum_{r=i}^nf(x,q,l,r)$
ans(i)=$\sum_xx*(h(x,i)-h(x-1,i))$
但是这样的做法不够优秀,有没有不利用随机的特性,严格$O(n^3)$的做法呢?
答案是有的。
其实很简单,观察发现转移的时候第一维是固定的,我们可以直接用dp(i,l,r)表示各种x的贡献和。
把上面ans(i)中的h展开,发现dp(i,l,r)=$\sum_x-f(x,i,l,r)$
转移没有变化,但初始化有变化。
初始化时的dp值怎么计算呢?
发现对于一段极长的区间[l,r],dp(0,l,r)=max(a(l)...a(r))-min(a(l-1),a(r+1)),对于非极长的区间dp(0,l,r)=0
发现#define一个for真好用233.
#include <cstdio>
#include <algorithm>
#define F(i,l,r) for(int i=l;i<=r;i++) const int N=,p=1e9+;
int n,q,a[N],f[][N][N],g[N][N],s1[][N][N],s2[][N][N]; int main() {
scanf("%d%d",&n,&q),a[]=a[n+]=1e9+;
F(i,,n) scanf("%d",&a[i]);
F(i,,n) {
int r=;
F(j,i,n) {
g[i][j]=i*(i-)/+(n-j)*(n-j+)/+(j-i+)*(j-i+)/,r=std::max(r,a[j]);
if(i==&&j==n) f[][i][j]=r;
else if(a[i-]>r&&a[j+]>r) f[][i][j]=(r-std::min(a[i-],a[j+])+p)%p;
}
}
F(i,,q) {
int s=i&,t=(i&)^;
F(j,,n) for(int k=n;k>=j;k--) s2[t][j][k]=(s2[t][j][k+]+1LL*f[t][j][k]*(n-k))%p;
F(j,,n) F(k,j,n) s1[t][j][k]=(s1[t][j-][k]+1LL*f[t][j][k]*(j-))%p,f[s][j][k]=(1LL*f[t][j][k]*g[j][k]+s1[t][j-][k]+s2[t][j][k+])%p;
}
F(i,,n) {int a1=; F(j,,i) F(k,i,n) a1=(a1+f[q&][j][k])%p; printf("%d%c",a1," \n"[i==n]);}
return ;
}
BZOJ4574 [Zjoi2016]线段树的更多相关文章
- bzoj4574:Zjoi2016线段树 dp
传送门 题解传送门 //Achen #include<algorithm> #include<iostream> #include<cstring> #includ ...
- bzoj 4574: [Zjoi2016]线段树
Description 小Yuuka遇到了一个题目:有一个序列a_1,a_2,?,a_n,q次操作,每次把一个区间内的数改成区间内的最大值,问 最后每个数是多少.小Yuuka很快地就使用了线段树解决了 ...
- 【UOJ#196】【BZOJ4574】[Zjoi2016]线段树
题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=4574 http://uoj.ac/problem/196 考虑数字随机并且值域够大,我们 ...
- Luogu3352 ZJOI2016 线段树 概率、区间DP
传送门 考虑对于每一个位置\(i\),计算所有可能的结果出现的概率. 定义一个区间\([l,r]\)为对于\(x\)的极大区间,当且仅当\(\max \limits _{i=l}^r \{a_i\} ...
- 【ZJOI2016】线段树
[ZJOI2016]线段树 ZJOI的题神啊. 我们考虑计算每个位置\(p\),它在操作过后变成第\(x\)个数的操作序列数. 我们枚举\(x\).我们先得到了\(L_x,R_x\)表示最左边比\(x ...
- @loj - 2093@ 「ZJOI2016」线段树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Yuuka 遇到了一个题目:有一个序列 a1,a2,..., ...
- bzoj3932--可持久化线段树
题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- codevs 1576 最长上升子序列的线段树优化
题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...
随机推荐
- 算法第四版 coursera公开课 普林斯顿算法 ⅠⅡ部分 Robert Sedgewick主讲《Algorithms》
这是我在网上找到的资源,下载之后上传到我的百度网盘了. 包含两部分:1:算法视频的种子 2:字幕 下载之后,请用迅雷播放器打开,因为迅雷可以直接在线搜索字幕. 如果以下链接失效,请在下边留言,我再更新 ...
- 消除ExtJS6的extjs-trila字样
- Linux的打印rpm包的详细信息的shell脚本
#!/bin/bash # list a content summary of a number of RPM packages # USAGE: showrpm rpmfile1 rpmfile2 ...
- LeetCode & Q66-Plus One-Easy
Array Description: Given a non-negative integer represented as a non-empty array of digits, plus one ...
- MVC Form 表单 提交 集合 及 复杂对象
public class Customer { public string FName{get;set;} public Address address{get;set;} } public clas ...
- Python内置函数(62)——exec
英文文档: exec(object[, globals[, locals]]) This function supports dynamic execution of Python code. obj ...
- spring boot 中active的profile会和标准配置合并吗
如下图,两个profile配置文件,一个默认的(application.properties),一个是test的. 活跃配置为test. spring.profiles.active=test ste ...
- oracle获取表字段属性
select b.COMMENTS,a.COLUMN_NAME,a.DATA_TYPE,a.DATA_LENGTH, a.DATA_PRECISION,a.DATA_SCALE,a.NULLABLE, ...
- 洛谷P1209-最大公约数与最小公倍数问题
一个萌新的成长之路 Discription 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P,Q的个数 条件: 1.P, ...
- django Form组件 上传文件
上传文件 注意:FORM表单提交文件要有一个参数enctype="multipart/form-data" 普通上传: urls: url(r'^f1/',views.f1), u ...