洛谷 P3246 - [HNOI2016]序列(单调栈+前缀和)
这道题为什么我就没想出来呢/kk
对于每组询问 \([l,r]\),我们首先求出区间 \([l,r]\) 中最小值的位置 \(x\),这个可以用 ST 表实现 \(\mathcal O(n\log n)-\mathcal O(1)\) 维护,那么显然 \(\forall l'\in[l,x],r'\in[x,r],\min\limits_{t\in[l',r']}a_t=a_x\),产生的贡献为 \((r-x+1)(x-l+1)a_x\),于是我们只用计算 \([x+1,r],[l,x-1]\) 两个区间的贡献即可。
这个东西怎么计算呢?考虑枚举区间的右端点 \(R\),我们要计算 \([x+1,R],[x+2,R],\cdots,[R,R]\) 这 \(R-x\) 个区间的最小值之和,我们记 \(pre_x\) 为最大的满足 \(y<x,a_y\le a_x\) 的 \(y\)——\(pre_x\) 显然可以用单调栈在线性时间内求出。再记序列 \(p_1,p_2,\cdots,p_k\) 满足 \(p_0=0,p_k=R,\forall i\in[1,k],p_{i-1}=pre_{p_i}\) 的序列(说白了就是单调栈求完 \(pre_R\) 之后,栈底到栈顶位置上元素的下标依次形成的序列),那么显然 \(\forall i\in[1,k],l\in(p_{i-1},p_i]\) 都有 \(\min\limits_{t=l}^xa_t=a_{p_i}\),也就是说 \(a_{p_i}\) 位置会成为 \(p_i-p_{i-1}\) 个位置的最小值。如果我们记 \(f_R\) 为 \([1,R],[2,R],\cdots,[R,R]\) 的最小值之和,那么根据之前的推论有递推式 \(f_R=f_{pre_R}+(R-pre_R)a_R\),可线性求出。
这里还有一个问题,那就是我们要计算 \([x+1,R],[x+2,R],\cdots,[R,R]\) 的贡献 instead of \([1,R],[2,R],\cdots,[R,R]\),也就是说我们要减去 \([1,R],[2,R],\cdots,[x,R]\) 的贡献。这东西又怎么求呢?很明显 \(p\) 序列有一个性质就是必定 \(\exist id\in[1,k]\) 满足 \(p_{id}=x\),正确性显然,并且容易注意到 \(\forall l\in[1,x],\min\limits_{t=l}^Ra_t=\min\limits_{t=l}^xa_t\),也就是说 \([1,R],[2,R],\cdots,[x,R]\) 的贡献其实就是 \([1,x],[2,x],\cdots,[x,x]\),因此只需拿 \(f_R-f_x\) 就可以得到 \([x+1,R],[x+2,R],\cdots,[R,R]\) 的贡献。
故最终 \([x+1,r]\) 的贡献之和就是 \(\sum\limits_{R=x+1}^rf_R-f_x\),这个显然前缀和随便算一下就行了。求 \([l,x-1]\) 的贡献也同理。
时间复杂度 \(n\log n\),瓶颈在于 RMQ。
const int MAXN=1e5;
const int LOG_N=18;
const int INF=0x3f3f3f3f;
int n,qu,a[MAXN+5],pre[MAXN+5],nxt[MAXN+5];
ll fl[MAXN+5],fr[MAXN+5],gl[MAXN+5],gr[MAXN+5];
pii st[MAXN+5][LOG_N+2];
pii query(int l,int r){
int k=31-__builtin_clz(r-l+1);
return min(st[l][k],st[r-(1<<k)+1][k]);
}
int main(){
scanf("%d%d",&n,&qu);a[0]=a[n+1]=-INF;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
stack<int> stk;stk.push(0);
for(int i=1;i<=n;i++){
while(!stk.empty()&&a[stk.top()]>=a[i]) stk.pop();
pre[i]=stk.top();stk.push(i);
} while(!stk.empty()) stk.pop();
stk.push(n+1);
for(int i=n;i;i--){
while(!stk.empty()&&a[stk.top()]>=a[i]) stk.pop();
nxt[i]=stk.top();stk.push(i);
}
// for(int i=1;i<=n;i++) printf("%d %d\n",pre[i],nxt[i]);
for(int i=1;i<=n;i++) fl[i]=fl[pre[i]]+1ll*a[i]*(i-pre[i]),gl[i]=gl[i-1]+fl[i];
for(int i=n;i;i--) fr[i]=fr[nxt[i]]+1ll*a[i]*(nxt[i]-i),gr[i]=gr[i+1]+fr[i];
for(int i=1;i<=n;i++) st[i][0]=mp(a[i],i);
for(int i=1;i<=LOG_N;i++) for(int j=1;j+(1<<i)-1<=n;j++)
st[j][i]=min(st[j][i-1],st[j+(1<<i-1)][i-1]);
while(qu--){
int l,r;scanf("%d%d",&l,&r);int p=query(l,r).se;
printf("%lld\n",1ll*a[p]*(p-l+1)*(r-p+1)+gr[l]-gr[p]-1ll*fr[p]*(p-l)+gl[r]-gl[p]-1ll*fl[p]*(r-p));
}
return 0;
}
洛谷 P3246 - [HNOI2016]序列(单调栈+前缀和)的更多相关文章
- 洛谷P3246 [HNOI2016]序列 [莫队]
传送门 思路 看到可离线.无修改.区间询问,相信一定可以想到莫队. 然而,莫队怎么转移是个大问题. 考虑\([l,r]\rightarrow[l,r+1]\)时答案会怎样变化?(左端点变化时同理) \ ...
- 洛谷P3246 [HNOI2016]序列(离线 差分 树状数组)
题意 题目链接 Sol 好像搞出了一个和题解不一样的做法(然而我考场上没写出来还是爆零0) 一个很显然的思路是考虑每个最小值的贡献. 预处理出每个数左边第一个比他小的数,右边第一个比他大的数. 那么\ ...
- 洛谷P3246 [HNOI2016]序列
传送门 题解 //minamoto #include<iostream> #include<cstdio> #define ll long long using namespa ...
- 洛谷P4198 楼房重建 单调栈+线段树
正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...
- 洛谷P4147 玉蟾宫 单调栈/悬线法
正解:单调栈/悬线法 解题报告: ummm这题我当初做的时候一点思路也没有只会暴力出奇迹:D(啊听说暴力好像能水过去呢,,, 然后当初是看的题解,然后学了下悬线法 然后就忘了:D 然后我现在看发现看不 ...
- 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询
题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i ...
- 洛谷 P4697 Balloons [CEOI2011] 单调栈/dp (待补充qwq)
正解:单调栈/dp 解题报告: 先放个传送门qwq 话说这题是放在了dp的题单里呢?但是听说好像用单调栈就可以做掉所以我就落实下单调栈的解法好了qwq (umm主要如果dp做好像是要斜率优化凸壳维护双 ...
- 洛谷P3400 仓鼠窝(单调栈)
P3400 仓鼠窝 题目描述 萌萌哒的Created equal是一只小仓鼠,小仓鼠自然有仓鼠窝啦. 仓鼠窝是一个由n*m个格子组成的行数为n.列数为m的矩阵.小仓鼠现在想要知道,这个矩阵中有多少个子 ...
- 洛谷 P1198 [JSOI2008]最大数——单调栈/线段树
先上一波题目 https://www.luogu.org/problem/P1198 题目要求维护后缀最大值 以及在数列的最后面添加一个数 这道题呢我们有两种做法 1.单调栈 因为只需要维护后缀最大值 ...
随机推荐
- 初学python-day3 元组
day2 列表已更新!
- 使用nexus搭建一个docker私服
使用nexus搭建docker私服 一.需求: 二.实现步骤 1.编写`docker-compose`文件,实现`nexus`的部署 2.修改/usr/lib/systemd/system/docke ...
- Oracle 11g 常用sql记录
--表备份 create table xxx_bak as select * from xxx; --表数据清除 truncate table xxx --锁表问题处理sql开始 select ses ...
- .NET Core TLS 协议指定被我钻了空子~~~
前言 此前,测试小伙伴通过工具扫描,平台TLS SSL协议支持TLS v1.1,这不安全,TLS SSL协议至少是v1.2以上才行,想到我们早已将其协议仅支持v1.3,那应该非我们平台问题.我依然自信 ...
- c 不同类型的指针
今天看到了一个问题:c里面,不同类型的指针是否可以互指呢?也就是不同类型的指针之间是否可以互相赋值,我想了想,对于32位机子而言,所有类型的指针都是4Byte(64位就是8Byte,这里只讨论32位) ...
- 前端面试手写代码——JS数组去重
目录 1 测试用例 2 JS 数组去重4大类型 2.1 元素比较型 2.1.1 双层 for 循环逐一比较(es5常用) 2.1.2 排序相邻比较 2.2 查找元素位置型 2.2.1 indexOf ...
- Python技法4:闭包
闭包:用函数代替类 有时我们会定义只有一个方法(除了__init__()之外)的类,而这种类可以通过使用闭包(closure)来替代.闭包是被外层函数包围的内层函数,它能够获取外层函数范围中的变量(即 ...
- Qt Creator打造VScode one dark pro主题配色
1.缘由 我之前习惯使用 vscode 进行开发,对 vscode 的 one dark pro 主题情有独钟.无奈公司需要使用 Qt Creator 进行日常开发,只能暂时舍弃 vscode,采用曲 ...
- 性能工具之代码级性能测试工具ContiPerf
前言 做性能的同学一定遇到过这样的场景:应用级别的性能测试发现一个操作的响应时间很长,然后要花费很多时间去逐级排查,最后却发现罪魁祸首是代码中某个实现低效的底层算法.这种自上而下的逐级排查定位的方法, ...
- 一文了解cookie
@ 目录 什么是Cookie? Cookie 的作用 Cookie原理 Cookie的分类 会话 Cookies 永久性 Cookies Cookie 的属性 name value Domain Pa ...