题面传送门

这道题为什么我就没想出来呢/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。

  1. const int MAXN=1e5;
  2. const int LOG_N=18;
  3. const int INF=0x3f3f3f3f;
  4. int n,qu,a[MAXN+5],pre[MAXN+5],nxt[MAXN+5];
  5. ll fl[MAXN+5],fr[MAXN+5],gl[MAXN+5],gr[MAXN+5];
  6. pii st[MAXN+5][LOG_N+2];
  7. pii query(int l,int r){
  8. int k=31-__builtin_clz(r-l+1);
  9. return min(st[l][k],st[r-(1<<k)+1][k]);
  10. }
  11. int main(){
  12. scanf("%d%d",&n,&qu);a[0]=a[n+1]=-INF;
  13. for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  14. stack<int> stk;stk.push(0);
  15. for(int i=1;i<=n;i++){
  16. while(!stk.empty()&&a[stk.top()]>=a[i]) stk.pop();
  17. pre[i]=stk.top();stk.push(i);
  18. } while(!stk.empty()) stk.pop();
  19. stk.push(n+1);
  20. for(int i=n;i;i--){
  21. while(!stk.empty()&&a[stk.top()]>=a[i]) stk.pop();
  22. nxt[i]=stk.top();stk.push(i);
  23. }
  24. // for(int i=1;i<=n;i++) printf("%d %d\n",pre[i],nxt[i]);
  25. 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];
  26. for(int i=n;i;i--) fr[i]=fr[nxt[i]]+1ll*a[i]*(nxt[i]-i),gr[i]=gr[i+1]+fr[i];
  27. for(int i=1;i<=n;i++) st[i][0]=mp(a[i],i);
  28. for(int i=1;i<=LOG_N;i++) for(int j=1;j+(1<<i)-1<=n;j++)
  29. st[j][i]=min(st[j][i-1],st[j+(1<<i-1)][i-1]);
  30. while(qu--){
  31. int l,r;scanf("%d%d",&l,&r);int p=query(l,r).se;
  32. 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));
  33. }
  34. return 0;
  35. }

洛谷 P3246 - [HNOI2016]序列(单调栈+前缀和)的更多相关文章

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

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

  2. 洛谷P3246 [HNOI2016]序列(离线 差分 树状数组)

    题意 题目链接 Sol 好像搞出了一个和题解不一样的做法(然而我考场上没写出来还是爆零0) 一个很显然的思路是考虑每个最小值的贡献. 预处理出每个数左边第一个比他小的数,右边第一个比他大的数. 那么\ ...

  3. 洛谷P3246 [HNOI2016]序列

    传送门 题解 //minamoto #include<iostream> #include<cstdio> #define ll long long using namespa ...

  4. 洛谷P4198 楼房重建 单调栈+线段树

    正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...

  5. 洛谷P4147 玉蟾宫 单调栈/悬线法

    正解:单调栈/悬线法 解题报告: ummm这题我当初做的时候一点思路也没有只会暴力出奇迹:D(啊听说暴力好像能水过去呢,,, 然后当初是看的题解,然后学了下悬线法 然后就忘了:D 然后我现在看发现看不 ...

  6. 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询

    题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i ...

  7. 洛谷 P4697 Balloons [CEOI2011] 单调栈/dp (待补充qwq)

    正解:单调栈/dp 解题报告: 先放个传送门qwq 话说这题是放在了dp的题单里呢?但是听说好像用单调栈就可以做掉所以我就落实下单调栈的解法好了qwq (umm主要如果dp做好像是要斜率优化凸壳维护双 ...

  8. 洛谷P3400 仓鼠窝(单调栈)

    P3400 仓鼠窝 题目描述 萌萌哒的Created equal是一只小仓鼠,小仓鼠自然有仓鼠窝啦. 仓鼠窝是一个由n*m个格子组成的行数为n.列数为m的矩阵.小仓鼠现在想要知道,这个矩阵中有多少个子 ...

  9. 洛谷 P1198 [JSOI2008]最大数——单调栈/线段树

    先上一波题目 https://www.luogu.org/problem/P1198 题目要求维护后缀最大值 以及在数列的最后面添加一个数 这道题呢我们有两种做法 1.单调栈 因为只需要维护后缀最大值 ...

随机推荐

  1. python中对列表的排序

    1.sort()对列表永久性的排序,首字母按照字母表的顺序排列 book=['python','java','c++','web'] book.sort() print(book) 结果如下: 2.向 ...

  2. [no_code][Beta]事后分析

    设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们要解决的目前的手写表单的电子化问题,办公电子化问题的一个key问题.定义十分清楚: 输入: 手写表单 ...

  3. stm32看门狗详细解答,看了觉得一下子明白了很多

    一.独立看门狗 STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效. 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路 ...

  4. Spring Cloud Alibaba 使用RestTemplate进行服务消费

    创建服务提供者工程 创建spring-cloud-alibaba-service-member工程,会员中心服务该服务提供用户会员信息. pom.xml <?xml version=" ...

  5. [源码解析] PyTorch 分布式(1)------历史和概述

    [源码解析] PyTorch 分布式(1)------历史和概述 目录 [源码解析] PyTorch 分布式(1)------历史和概述 0x00 摘要 0x01 PyTorch分布式的历史 1.1 ...

  6. Delphi的手机程序隐藏顶部信号栏

    把TForm的BorderStyle设置为None 记之!

  7. C语言的“隐式函数声明”违背了 “前置声明” 原则

    这个问题来源于小组交流群里的一个问题: 最终问题落脚在 : 一个函数在main中调用了,必须在main之前定义或者声明吗? 我在自己的Centos上做了实验,结果是函数不需要,但是结构体(变量也要)需 ...

  8. 【AI测试】人工智能 (AI) 测试--开篇

    人工智能测试 什么是人工智能,人工智能是怎么测试的.可能是大家一开始最想了解的.大家看图中关于人工智能的定义.通俗点来说呢,就是 让机器实现原来只有人类才能完成的任务:比如看懂照片,听懂说话,思考等等 ...

  9. 运行级别和找回root密码

    运行级别说明 0 :关机 1 :单用户 [类似安全模式,这个模式可以帮助找回root密码 2:多用户状态没有网络服务 3:多用户状态有网络服务 [使用] 4:系统未使用保留给用户 5:图形界面 6:系 ...

  10. Python3使用request/urllib库重定向问题

    禁止自动重定向 python3的urllib.request模块发http请求的时候,如果服务器响应30x会自动跟随重定向,返回的结果是重定向后的最终结果而不是30x的响应结果. request是靠H ...