『序列 莫队 dp预处理』
<更新提示>
<第一次更新>
<正文>
序列
Description
给定长度为n的序列:a1,a2,…,an,记为a[1:n]。
类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar。若1≤l≤s≤t≤r≤n,则称a[s:t]是a[l:r]的子序列。
现在有q个询问,每个询问给定两个数l和r,1≤l≤r≤n,求a[l:r]的不同子序列的最小值之和。
例如,给定序列5,2,4,1,3,询问给定的两个数为1和3,那么a[1:3]有6个子序列a[1:1],a[2:2],a[3:3],a[1:2],a[2:3],a[1:3],这6个子序列的最小值之和为5+2+4+2+2+2=17。
Input Format
输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数。
接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i个元素的值。
接下来q行,每行包含两个整数l和r,代表一次询问。
Output Format
对于每次询问,输出一行,代表询问的答案。
Sample Input
5 5
5 2 4 1 3
1 5
1 3
2 4
3 5
2 5
Sample Output
28
17
11
11
17
解析
回答若干个静态的区间询问,思路是莫队。
假设我们已经得到了区间\([l,r]\)的答案,直接考虑如何转移到\([l,r+1]\)。显然,我们只需要考虑包含\(r+1\)这一个点的子序列\([l,r+1],[l+1,r+1],...,[r+1,r+1]\)即可。要求的是最小值之和,我们就设\([l,r+1]\)在\(a\)序列上的区间最小值为\(a_p\),位置是\(p\),那么所有左端点在\([l,p]\)之间的区间的答案就都是\(a_p\),总共的贡献为\(a_p*(p-l+1)\),这个问题显然可以用\(ST\)表解决。
那么剩下的那些区间我们考虑用\(dp\)来计算答案。设\(f[i][j]\)代表右端点为\(j\),左端点在\([i,j]\)之间的答案之和,那么我们要求的就是\(f[p+1][r+1]\)。记录下\(prep_i\)代表\(a\)序列中\(a_i\)左边第一个比他小的元素的位置(单调栈解决),状态转移方程就是:$$f[i][j]=f[i][prep_j]+a_j*(j-prep_j)$$。
发现状态转移方程与\(i\)无关,直接将第一维舍去,那么\(f[j]\)的定义就是右端点为\(j\)的所有区间的答案之和。继续考虑原问题,发现必然存在一个点\(x\)满足\(prep_x=p\),\(f[r+1]=a_{r+1}*(r+1-prep_{r+1})+...+a_x*(x-p)+f[p]\),那么我们原来要求的\(f[p+1][r+1]\)其实可以表示为\(f[r+1]-f[p]\),然后预处理出\(f\)数组,就可在莫队当中\(O(1)\)转移了。
当然,我们还需要处理出反方向的\(f\)数组,以便莫队向左转移。如果是删除操作的话,就减去加入这个点的时候带来的贡献即可。
\(Code:\)
#include <bits/stdc++.h>
using namespace std;
const int N = 100200 , MaxlogN = 25 , INF = 2e9;
int n,m,a[N],size;
int Min[N][MaxlogN],Log2[N],Pow2[MaxlogN];
int prep[N],next[N],Stack[N],top;
long long ans[N],fl[N],fr[N],tot;
struct Query{int l,r,id;}q[N];
inline void init(void)
{
Pow2[0] = 1 , a[0] = a[n+1] = INF;
for (int i=1;i<=MaxlogN-2;i++)
Pow2[i] = Pow2[i-1] << 1;
for (int i=2;i<=n;i++)
Log2[i] = Log2[i>>1] + 1;
for (int i=1;i<=n;i++)
Min[i][0] = i;
for (int k=1;k<=Log2[n];k++)
for (int i=1;i+Pow2[k-1]-1<=n;i++)
if ( a[ Min[i][k-1] ] < a[ Min[i+Pow2[k-1]][k-1] ] )
Min[i][k] = Min[i][k-1];
else Min[i][k] = Min[i+Pow2[k-1]][k-1];
top = 0;
for (int i=1;i<=n;i++)
{
while ( top && a[Stack[top]] > a[i] )
next[ Stack[top--] ] = i;
prep[i] = Stack[top] ; Stack[++top] = i;
}
while ( top )
{
prep[ Stack[top] ] = Stack[top-1];
next[ Stack[top] ] = n+1;
top--;
}
}
inline int query(int l,int r)
{
int k = Log2[r-l+1];
if ( a[ Min[l][k] ] < a[ Min[r-Pow2[k]+1][k] ] )
return Min[l][k];
else return Min[r-Pow2[k]+1][k];
}
inline void input(void)
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<=m;i++)
scanf("%d%d",&q[i].l,&q[i].r) , q[i].id = i;
}
inline void dp(void)
{
for (int i=1;i<=n;i++)
fr[i] = fr[prep[i]] + 1LL * a[i] * (i-prep[i]);
for (int i=n;i>=1;i--)
fl[i] = fl[next[i]] + 1LL * a[i] * (next[i]-i);
}
inline bool compare(Query p1,Query p2)
{
if ( (p1.l/size) ^ (p2.l/size) )
return p1.l < p2.l ;
else if ( (p1.l/size) & 1 )
return p1.r < p2.r ;
else return p1.r > p2.r ;
}
inline void insert1(int l,int r)
{
int p = query(l,r);
tot += ( 1LL * a[p] * (p-l+1) + fr[r] - fr[p] );
}
inline void insert2(int l,int r)
{
int p = query(l,r);
tot += ( 1LL * a[p] * (r-p+1) + fl[l] - fl[p] );
}
inline void remove1(int l,int r)
{
int p = query(l,r);
tot -= ( 1LL * a[p] * (p-l+1) + fr[r] - fr[p] );
}
inline void remove2(int l,int r)
{
int p = query(l,r);
tot -= ( 1LL * a[p] * (r-p+1) + fl[l] - fl[p] );
}
inline void CaptainMo(void)
{
double val = sqrt(1.0*m*2/3);
if ( val > n || val < 500 ) size = sqrt(n);
else size = n * 1.0 / val;
sort( q+1 , q+m+1 , compare );
int l = 1 , r = 0;
for (int i=1;i<=m;i++)
{
int ql = q[i].l , qr = q[i].r;
while ( l > ql ) insert2(--l,r);
while ( r < qr ) insert1(l,++r);
while ( l < ql ) remove2(l++,r);
while ( r > qr ) remove1(l,r--);
ans[ q[i].id ] = tot;
}
}
int main(void)
{
input();
init();
dp();
CaptainMo();
for (int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
return 0;
}
<后记>
『序列 莫队 dp预处理』的更多相关文章
- 学习笔记——不带修序列莫队 (luogu2079)小B的询问
莫队是一种对于询问的离线算法 时间复杂度:O(\(n \sqrt n\)) 大致思想就是 首先将询问离线,然后对原序列分块,使得每一个\(l和r\)都在一个块里 然后按照左节点排序,若所在的块相等,就 ...
- [HNOI2016]序列(莫队,RMQ)
[HNOI2016]序列(莫队,RMQ) 洛谷 bzoj 一眼看不出来怎么用数据结构维护 然后还没修改 所以考虑莫队 以$(l,r-1) -> (l,r)$为例 对答案的贡献是$\Sigma_ ...
- BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]
4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ...
- [bzoj4540][Hnoi2016][序列] (莫队算法+单调栈+st表)
Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar.若1≤l≤s≤t≤r≤n,则称a ...
- BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)
BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...
- bzoj 4540 [HNOI 2016] 序列 - 莫队算法 - Sparse-Table - 单调栈
题目传送门 传送点I 传送点II 题目大意 给定一个长度为$n$的序列.询问区间$[l, r]$的所有不同的子序列的最小值的和. 这里的子序列是连续的.两个子序列不同当且仅当它们的左端点或右端点不同. ...
- 【BZOJ4540】[Hnoi2016]序列 莫队算法+单调栈
[BZOJ4540][Hnoi2016]序列 Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,a ...
- bzoj 4540: [Hnoi2016]序列 莫队
题目: 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- 1,ar.若1≤l≤s≤t≤r≤n,则称a[s:t]是a ...
- Bzoj 3809: Gty的二逼妹子序列 莫队,分块
3809: Gty的二逼妹子序列 Time Limit: 35 Sec Memory Limit: 28 MBSubmit: 868 Solved: 234[Submit][Status][Dis ...
随机推荐
- MySQL单表最大记录数不能超过多少?
MySQL单表最大记录数不能超过多少? 很多人困惑这个问题.其实,MySQL本身并没有对单表最大记录数进行限制,这个数值取决于你的操作系统对单个文件的限制本身. 从性能角度来讲,MySQL单表数据不要 ...
- Jira未授权SSRF漏洞复现(CVE-2019-8451)
0x00 漏洞背景 Jira的/plugins/servlet/gadgets/makeRequest资源存在SSRF漏洞,原因在于JiraWhitelist这个类的逻辑缺陷,成功利用此漏洞的远程攻击 ...
- flink dataset join笔记
1.dataset的join连接,通过key进行关联,一般情况下的join都是inner join,类似sql里的inner join key包括以下几种情况: a key expression a ...
- 【MySQL】备份和恢复
语法 mysqldump -uslave -p -h127.0.0.1 --single-transaction --set-gtid-purged=OFF database1 table1 tabl ...
- 并发编程(六)--进程/线程池、协程、gevent第三方库
一.进程/线程池 1.进程池 (1)什么是进程池 如果需要创建的子进程数量不大,可以直接利用multiprocess中的Process来创建.但是当需要创建上百个或上千个,手动创建就较为繁琐,这时就可 ...
- Windows Server 2008 R2(x64) IIS7+PHP5.6.30(FastCGI)环境搭建
相关软件下载: 1.PHP下载地址: http://windows.php.net/downloads/releases/ 1.安装Microsoft Visual C++ 2012 Redistri ...
- 在ISTIO中让GRAFANA跑起来
比较轻车熟路了. 这个GRAFANA内,已集成了ISTIO常见的DASHBOARD了. 一,映射本地端口 kubectl port-forward -n istio-system $(kubectl ...
- 201871010110 - 李华 《面向对象程序设计(java)》第二周学习总结
第一部分:理论知识学习部分 一.简单的Java程序应运程序 1.标识符0标识符由字母.下划线.美元符号和数字组成,且第一个符号不能为数字. 标识符可用作:类名.对象名.变量名.方法名.数组名.文件 ...
- oracle在windows(含客户端工具pl/sql安装)下安装
安装Oracle服务器端 系统默认创建的数据库名称为orcl,可自行修改. 全局数据库名(用来唯一标示Oracle数据库,每个数据库至少由一个Oracle系统标识符(SID)引用),orcl,后面称为 ...
- JMeter5.1开发SMTP协议接口脚本
jmeter可以测试发邮件和读取邮件. 发送邮件 上图部分解释: Server:邮件发送服务 Port:发邮件端口,不加密25,加密465,如果是465端口,Security settings 需要选 ...