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

题解:

这题思路莫名清晰,一看没有修改果断上莫队

然后移动指针r时会产生(r-l+1)个新区间 考虑每一个区间的最小值是谁,我们就统计一个数对哪些区间有贡献

很容易得知:设pre[i]为i之前第一个比a[i]小的数,于是i的贡献就是(i-pre[i]+1)*a[i] 而pre[i]的贡献为(pre[i]-pre[pre[i]]+1)*a[pre[i]] 以此类推 设[l,r]区间的最小值所在位置为kt,kt产生的贡献即为(kt-i+1)*a[kt],所以pre[i]一直往前走到kt位置 

然后为了统计的效率,我们处理一个前缀和数组,含义大概就是上面那个沿着pre走,走到0为止的和

sum[i]可以递推出来:sum[i]=sum[pre[i]]+(i-pre[i]+1)*a[i].

L指针的移动同理,改成减去即可

然后pre数组单调栈处理

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ls (node<<1)
#define rs (node<<1|1)
using namespace std;
const int N=,INF=;
typedef long long ll;
int gi(){
int str=,f=;char ch=getchar();
while(ch>'' || ch<''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<='')str=str*+ch-'',ch=getchar();
return str*f;
}
int n,m,a[N],Tree[N*],ct,pre[N],nxt[N],q[N],maxdep,f[N][];
ll as=,suml[N],sumr[N],ans[N];
struct AKK{
int l,r,id;
}ques[N];
bool comp(const AKK &p,const AKK &qq)
{
if(p.l/ct!=qq.l/ct)return p.l/ct<qq.l/ct;
return p.r<qq.r;
}
void prework()
{
q[]=;int r=;
for(int i=;i<=n;i++)
{
while(r> && a[i]<=a[q[r]])r--;
pre[i]=q[r];
q[++r]=i;
}
r=;q[]=n+;
for(int i=n;i>=;i--)
{
while(r> && a[i]<=a[q[r]])r--;
nxt[i]=q[r];
q[++r]=i;
}
for(int i=;i<=n;i++)suml[i]=suml[pre[i]]+(ll)(i-pre[i])*a[i];
for(int i=n;i>=;i--)sumr[i]=sumr[nxt[i]]+(ll)(nxt[i]-i)*a[i];
}
int Ask(int l,int r)
{
int k=(int)(log(r-l+)/log()),to=r-(<<k)+;
if(a[f[l][k]]<=a[f[to][k]])return f[l][k];
return f[to][k];
}
ll pl(int l,int r)
{
int kt=Ask(l,r);
ll cnt=(ll)(kt-l+)*a[kt];
cnt+=suml[r]-suml[kt];
return cnt;
}
ll pr(int l,int r)
{
int kt=Ask(l,r);
ll cnt=(ll)(r-kt+)*a[kt];
cnt+=sumr[l]-sumr[kt];
return cnt;
}
void work()
{
int l=,r=;as=a[];
for(int i=;i<=m;i++)
{
while(r<ques[i].r)r++,as+=pl(l,r);
while(r>ques[i].r)as-=pl(l,r),r--;
while(l<ques[i].l)as-=pr(l,r),l++;
while(l>ques[i].l)l--,as+=pr(l,r);
ans[ques[i].id]=as;
}
}
void gf()
{
for(int j=;j<=maxdep;j++)
for(int i=;i+(<<j)-<=n;i++)
{
int to=i+(<<(j-));
if(a[f[i][j-]]>a[f[to][j-]])f[i][j]=f[to][j-];
else f[i][j]=f[i][j-];
}
}
int main()
{
n=gi();m=gi();
for(int i=;i<=n;i++)a[i]=gi(),f[i][]=i;
maxdep=log(n)/log();
gf();
for(int i=;i<=m;i++)ques[i].l=gi(),ques[i].r=gi(),ques[i].id=i;
ct=sqrt(n);
sort(ques+,ques+m+,comp);
prework();
work();
for(int i=;i<=m;i++)printf("%lld\n",ans[i]);
return ;
}

【HNOI2016】序列 莫队+单调栈+RMQ的更多相关文章

  1. [HNOI2016]序列(莫队,RMQ)

    [HNOI2016]序列(莫队,RMQ) 洛谷  bzoj 一眼看不出来怎么用数据结构维护 然后还没修改 所以考虑莫队 以$(l,r-1) -> (l,r)$为例 对答案的贡献是$\Sigma_ ...

  2. BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)

    BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...

  3. 【BZOJ4540】[Hnoi2016]序列 莫队算法+单调栈

    [BZOJ4540][Hnoi2016]序列 Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,a ...

  4. [luogu3246][bzoj4540][HNOI2016]序列【莫队+单调栈】

    题目描述 给定长度为n的序列:a1,a2,...,an,记为a[1:n].类似地,a[l:r](1<=l<=r<=N)是指序列:al,al+1,...,ar-1,ar.若1<= ...

  5. [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 ...

  6. BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]

    4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ...

  7. BZOJ.4826.[AHOI/HNOI2017]影魔(树状数组/莫队 单调栈)

    BZOJ LOJ 洛谷 之前看\(mjt\)用莫队写了,以为是一种正解,码了3h结果在LOJ T了没A= = 心态爆炸(upd:发现是用C++11(NOI)交的,用C++11交就快一倍了...) 深刻 ...

  8. [BZOJ4540][HNOI2016]序列 莫队

    4540: [Hnoi2016]序列 Time Limit: 20 Sec  Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ...

  9. 洛谷P3246 [HNOI2016]序列 [莫队]

    传送门 思路 看到可离线.无修改.区间询问,相信一定可以想到莫队. 然而,莫队怎么转移是个大问题. 考虑\([l,r]\rightarrow[l,r+1]\)时答案会怎样变化?(左端点变化时同理) \ ...

随机推荐

  1. Beta阶段敏捷冲刺每日报告——Day0

    下一阶段需要改进完善的功能: 搜索框在Firefox和IE中显示不正常问题 下一阶段新增的功能: ToDoList功能:针对博主的功能,在博主登录之后可以添加和修改待办事项,每个事项包括标题.内容.日 ...

  2. 使用Spark MLlib进行情感分析

    使用Spark MLlib进行情感分析             使用Spark MLlib进行情感分析 一.实验说明 在当今这个互联网时代,人们对于各种事情的舆论观点都散布在各种社交网络平台或新闻提要 ...

  3. 成功案例分享:raid5两块硬盘掉线数据丢失恢复方法

    1. 故障描述    本案例是HP P2000的存储vmware exsi虚拟化平台,由RAID-5由10块lT硬盘组成,其中6号盘是热备盘,由于故障导致RAID-5磁盘阵列的两块盘掉线,表现为两块硬 ...

  4. 改变input的placeholder颜色

    input::-webkit-input-placeholder{ color:#666; } input::-ms-input-placeholder{ color:#666; } input::- ...

  5. python hashlib、hmac模块

    一.hashlib模块 import hashlib m = hashlib.md5() m.update(b"Hello") print(m.hexdigest()) m.upd ...

  6. Python扩展模块——调用WindowsAPI(pywin32的简单使用)

    这块使用的比较少,只用到了模拟键盘按键, 调用鼠标比较费事,是通过像素坐标实现的,如果没有特殊需求或万不得已不建议使用 import win32con import win32api win32api ...

  7. js 开发注意事项

    涉及api post 请求的, 涉及sqlite 存储的, conent 用encodeURIComponent, decodeURIComponent ,处理 JSON.parse 最好加上try ...

  8. python 判断变量是否是 None 的三种写法

    代码中经常会有变量是否为None的判断,有三种主要的写法:第一种是`if x is None`:第二种是 `if not x:`:第三种是`if not x is None`(这句这样理解更清晰`if ...

  9. solr云的简单搭建(了解)

    1.认识系统架构 1.1.集群概述 1.1.1.单点服务器的问题 我们之所以要学习集群,是因为单点服务器,存在一系列的问题. 我们以前学习的JavaEE项目,都是部署在一台Tomcat上,所有的请求, ...

  10. 小tip: 使用CSS将图片转换成黑白(灰色、置灰)

    可能早就知道,像汶川这种糟糕的日子网站全灰在IE下是可以轻松实现的(filter: gray;),不过,当时,其他浏览器是无解的.不过,时代发展,如今,CSS3的逐步推进,我们也开始看到“黑白效果”大 ...