[Bzoj4540][Hnoi2016] 序列(莫队 + ST表 + 单调队列)

4540: [Hnoi2016]序列


 

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1567  Solved: 718
[Submit][Status][Discuss]

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


 

  输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数。接下来一行,包含n个整数,以空格隔开
,第i个整数为ai,即序列第i个元素的值。接下来q行,每行包含两个整数l和r,代表一次询问。

Output


 

  对于每次询问,输出一行,代表询问的答案。

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

 

HINT


 

 

1 ≤N,Q ≤ 100000,|Ai| ≤ 10^9

分析:


也许是我比较傻吧, 我把分块那里block[i] = i / tot +1打成了 block[i] = block[i] / tot + 1,超时了半天,调不出来……

题目又是没有修改,只有查询,可以联想到莫队算法。

题目要求是求一个大区间内,每个子区间最小值之和。我们可以看一下,如果已知一个区间[l,r],那么如果要得到[l,r + 1],我们会把[r + 1]的数添加进来。当这个数添加进来会多产生r - l + 2个子区间,那么如何处理这个子区间呢,就算是用st表 暴力去查询 这 r - l + 2个区间复杂度结合每一次也是很高的。

我们可以分析一下:如果我们找到[l,r + 1]里面的最小值,它所在位置为k。那么[l,k]这段区间的点为左端点和[r +1]所产生的 k - l + 1个区间都是以[k]所在数为最小值,那么贡献为(k - l + 1) * a[k],剩下的就是[k + 1,r + 1]这段区间了。

当我们知道一个数i左边第一个小于等于它的数的下标lm[i],所以[lm[i] + 1,i - 1]中间的值都是大于[i]的数的。所以以[lm[i] +1,i]的数都以[i]的数为最小值。设sumr[i]表示以i为右端点的合法区间的答案,那么sumr[i] = sumr[lm[i]] + (i  - lm[i]) * a[i]。发现我们的sumr数组是类似于前缀和的形式,最后我们用sum[r +1] - sum[k]就为[k + 1,r + 1]这段区间答案。

最终一个区间答案为ans =  (k - l + 1) * a[k] + sumr[r +1] - sum[k]。

删除同理,在左端点处添加删除只需维护rm[i]和suml[i]。求区间最小值的位置可以用st表,o(nlogn)的转移,o(1)的查询。求一个数左右第一个不大于它的数可以用单调队列,当一个数被另一个数踢出时,这个数离它最近的相应方向上的第一个不大于它的数就为另一个数。再加上莫队算法(nsqrt(n))总时间复制度为o(nlogn + nsqrt(n))


 ST表:


类似于动态转移的思想,我们知道区间[l,r]的最小值,就可以推出区间[l,r + 1]的最小值,但是st表运用了倍增的思想(类似lca)。

我们知道了每个数向右2^(j - 1) 的最小值,就能拓展到每个数向右2 ^ j 的最小值。

转移方程为 

st[i][j] = min(st[i][j - 1],st[i + (1 << j - 1)][j - 1]);

 

具体详见代码

附上AC代码: 

 


 

 

# include <iostream>
# include <cmath>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
const int N = 2e5 + 12;
int block[N],tot,n,m;
struct data{int l,r,id;
bool operator <(const data & other)const{if(block[l] == block[other.l])return r < other.r;return block[l] < block[other.l];
}
}q[N];
int st[N][31],a[N],mn[N];
int stack[N],cnt;
int lm[N],rm[N];
long long suml[N],sumr[N],num,ans[N];
int query(int x,int y){return  a[x] < a[y] ? x : y;
}
int Rmq(int L,int R)
{   if(L > R)swap(L,R);int k = mn[R - L + 1];return query(st[L][k],st[R - (1 << k) + 1][k]);
}
void updatal(int x,int y,int z){int pos = Rmq(x,y);num +=(1ll * (y - pos + 1) * a[pos] + sumr[x] - sumr[pos]) * z; 
};
void updatar(int x,int y,int z){int pos = Rmq(x,y);num +=(1LL * (pos - x + 1) * a[pos] + suml[y] - suml[pos]) * z; 
};
void Modui(){int L = 1,R = 0; num = 0;for (int i = 1;i <= m;++i){while (R < q[i].r) updatar(L,R + 1,1),R++;while (L > q[i].l) updatal(L - 1,R,1),L--;while (R > q[i].r) updatar(L,R,-1),R--;while (L < q[i].l) updatal(L,R,-1),L++;ans[q[i].id] = num;}
}
void work(){cnt = 0;for(int i = 1;i <= n;i++){while(cnt && a[stack[cnt]] >= a[i])rm[stack[cnt--]] = i;stack[++cnt] = i;}while(cnt)rm[stack[cnt--]] = n + 1;for(int i = n;i >= 1;i--){while(cnt && a[stack[cnt]] >= a[i])lm[stack[cnt--]] = i;stack[++cnt] = i;}for(int i = 1;i <= n;i++){suml[i] = suml[lm[i]] + 1LL * (i - lm[i]) * a[i];}for(int i = n;i >= 1;i--){sumr[i] = sumr[rm[i]] + 1LL * (rm[i] - i) * a[i];}
}
void init(){mn[0] = -1;for(int i = 1;i <= n;i++){mn[i]=((i & (i-1))==0) ? mn[i-1]+1 : mn[i-1];st[i][0] = i;}for (int j = 1;j <= mn[n];j++){for (int i = 1;i + (1 << j) - 1 <= n;i++){st[i][j] = query(st[i][j - 1],st[i + (1 << j - 1)][j - 1]);}}work();
}
int main(){scanf("%d %d",&n,&m);tot = sqrt(n);for(int i = 1;i <= n;i++){scanf("%d",&a[i]);block[i] = i / tot + 1;}init();for(int i = 1;i <= m;i++){scanf("%d %d",&q[i].l,&q[i].r);q[i].id = i;}sort(q + 1,q + m + 1); Modui();for(int i = 1;i <= m;i++){printf("%lld\n",ans[i]);}return 0;
}

 

 

 

转载于:https://www.cnblogs.com/lzdhydzzh/p/7656539.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/415594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2 微信公众号开发 服务器配置 Token验证

服务器配置的主要难点就是Token验证。 官方文档&#xff1a;https://mp.weixin.qq.com/wiki?tresource/res_main&idmp1445241432 接入指南&#xff1a;https://mp.weixin.qq.com/wiki?tresource/res_main&idmp1421135319 用户服务器端主要需要做的工作&#xff0c;…

Android 10分钟集成极光推送

1、首先申请key https://www.jiguang.cn/accounts/login/form 2、app build.gradle添加jar依赖 compile cn.jiguang.sdk:jpush:3.0.7 compile cn.jiguang.sdk:jcore:1.1.3 compile me.leolin:ShortcutBadger:1.1.16aar//消息桌面显示 注意最新依赖是&#xff1a; compile c…

Python requests介绍之接口介绍

Python requests介绍 引用官网介绍 Requests 唯一的一个非转基因的 Python HTTP 库&#xff0c;人类可以安全享用。 Requests 允许你发送纯天然&#xff0c;植物饲养的 HTTP/1.1 请求&#xff0c;无需手工劳动。你不需要手动为 URL 添加查询字串&#xff0c;也不需要对 POST 数…

前端学习(2623):Vuex初步识别

Vuex 是什么&#xff1f; Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window)&#x…

3 微信公众号开发 接受普通消息

用户如果在公众号发送内容&#xff0c;微信服务器会把消息转发到我们到服务器上&#xff0c;我们需要及时做出处理&#xff0c;给用户反馈。 文档地址&#xff1a;https://mp.weixin.qq.com/wiki?tresource/res_main&idmp1421140453 例如&#xff0c;在微信公众号发送消…

Android 动画以view中心点旋转动画

旋转180度 Animation anim new RotateAnimation(0f, 180f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); anim.setFillAfter(true); // 设置保持动画最后的状态 anim.setDuration(500); // 设置动画时间 anim.setInterpolator(new AccelerateInterpo…

Linux 查看系统硬件信息

Linux 查看系统硬件信息(实例详解)linux查看系统的硬件信息&#xff0c;并不像windows那么直观&#xff0c;这里我罗列了查看系统信息的实用命令&#xff0c;并做了分类&#xff0c;实例解说。 cpu lscpu命令&#xff0c;查看的是cpu的统计信息. blueblue-pc:~$ lscpu Archit…

简易表格编辑器

SMMS有个建表工具,尝试使用HTML模仿出一个简单的做为练习. 截图: 一.实现SMMS建表工具的操作 点击单元格,进入编辑状态.按TAB切换单元格按方向箭切换单元格按空格设定取消主键列二.实现思路: 1.DOM结构使用div(行)span(列) <div><span></span><span>&l…

前端学习(2624):state

State # 单一状态树 在 Scrimba 上尝试这节课 Vuex 使用单一状态树——是的&#xff0c;用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT (opens new window))”而存在。这也意味着&#xff0c;每个应用将仅仅包含一个 store 实例。单一状态树让…

Android 向右滑返回,退出当前activity

demo链接&#xff1a;https://download.csdn.net/download/meixi_android/10826597 实现效果: 纯原生类实现方法&#xff1a; 1、自定义侧滑基类SwipeBackActivity public class SwipeBackActivity extends FragmentActivity implements SwipeBackActivityBase {private Swi…

4 微信公众号开发 被动回复消息 回复没有反应怎么办

接收到用户的消息&#xff0c;我们需要做出反馈。 文档地址&#xff1a;https://mp.weixin.qq.com/wiki?tresource/res_main&idmp1421140543 官方返回的数据格式是xml&#xff0c;我们需要转化为json。获取数据&#xff0c;构造xml在返回就OK了。 核心代码&#xff1a; …

Linux系统的远程登录

Linux大多应用于服务器&#xff0c;而服务器不可能像PC一样放在办公室&#xff0c;它们是放在IDC机房的&#xff0c;所以我平时登录linux系统都是通过远程登录的。Linux系统中是通过ssh服务实现的远程登录功能。默认ssh服务开启了22端口&#xff0c;而且当我们安装完系统时&…

更新——Canvas画布动画效果之实现倒计时

Hello&#xff0c;大家好&#xff01; 小W复活啦&#xff01;继续欢乐的给大家更博&#xff0c;输送新知识~~ 不开玩笑啦&#xff01;秒进正题~~~ 上次更博&#xff0c;小W给大家介绍了Canvas画布的基础部分&#xff0c;以及实现了一个由7*10点阵图显示的倒计时的基本架构。 上…

5 微信公众号开发 获取 access_token

在使用微信公众号接口中&#xff0c;需要access_token。access_token是公众号的全局唯一凭证。可以理解为我们服务器的身份证。 总结以上说明&#xff0c;access_token需要做到以下两点&#xff1a; 1.因为access_token有2个小时的时效性&#xff0c;要有一个机制保证最长2个…

Linux平台上最常用的翻译工具—StarDict(星际译王)。

1、打开终端&#xff0c;输入命令$sudo apt-get install stardict&#xff0c;开始下载安装。 2、安装完成后&#xff0c;打开后选择左下角取词选项&#xff0c;即可完成屏幕取词功能。 3、以上是实现的是在线翻译功能&#xff0c;要实现离线翻译&#xff0c;需要下载离线辞…

Android TextView 设置文字背景色或文字颜色,字体阴影,字体样式

//第一个字符变色String copiesStr_notic tv_notic.getText().toString().trim();SpannableString spannableString2 new SpannableString(copiesStr_notic);//0 第一行缩进像素 , SizeUtils.dp2px(15)非第一行缩进像素Paint mPaintnew Paint();float wmPaint.measureText(cop…

resharper license server

2018-5-14更新 http://jetbrains-a.pw good 2018-4-17 更新 http://jetbrains.tools bad 144.202.4.96 good 2017-10-25 更新 http://idea.iteblog.com/key.php bad http://idea.lanyus.com/ bad http://jetbrains.tech bad http://www.iteblog.com/idea/key.php bad http://xi…

ubuntu man手册完善

ubuntu man手册完善 Linux提供了丰富的帮助手册&#xff0c;当你需要查看某个命令的参数时不必到处上网查找&#xff0c;只要man一下即可。 sudo apt-get install manpages-dev sudo apt-get install manpages-posix sudo apt-get install manpages-posix-dev sudo apt-get ins…