[HNOI2016]序列

Tea神题解 Kelin神题解

对于莫队算法最主要的是如何快速算出[l,r]→[l,r+1][l,r]\to[l,r+1][l,r]→[l,r+1]对答案的贡献的变化。
当询问区间发生上述变化时[l,r]→[l,r+1][l,r]\to [l,r+1][l,r]→[l,r+1]不难发现子区间增加这些:[l,r+1],[l+1,r+1],…,[r,r+1],[r+1,r+1][l,r+1],[l+1,r+1],\dots,[r,r+1],[r+1,r+1][l,r+1],[l+1,r+1],…,[r,r+1],[r+1,r+1]总共r−l+2r-l+2r−l+2个子区间[l→r+1,r+1][l\to r+1,r+1][l→r+1,r+1],需要求出他们对答案的贡献即每个区间的区间最小值之和。

考虑求出[l,r+1][l,r+1][l,r+1]区间最小值的位置是ppp,不难得知这些子区间[l→p,r+1][l\to p,r+1][l→p,r+1]的最小值都是apa_pap​,这部分对答案的贡献是ap×(p−l+1)a_p×(p-l+1)ap​×(p−l+1)这里可以用ST表预处理快速求出。

而对于这些子区间[p+1→r+1,r+1][p+1\to r+1,r+1][p+1→r+1,r+1]
预处理fif_ifi​:表示以iii为区间右端点的最小值之和
fi=fLi+ai×(i−Li)f_i=f_{L_i}+a_i×(i-L_i)fi​=fLi​​+ai​×(i−Li​)
LiL_iLi​表示iii左边第一个小于等于aia_iai​的位置。(可以用单调栈预处理)

不难发现一定有xxx使得Lx=pL_x=pLx​=p于是有fr+1=ar+1×(r+1−Lr+1)+⋯+ax×(x−p)+fpf_{r+1}=a_{r+1}×(r+1-L_{r+1})+\dots+a_x×(x-p)+f_pfr+1​=ar+1​×(r+1−Lr+1​)+⋯+ax​×(x−p)+fp​
于是子区间[p+1→r+1,r+1][p+1\to r+1,r+1][p+1→r+1,r+1]对答案的贡献是fr+1−fpf_{r+1}-f_pfr+1​−fp​

对于[l,r]→[l−1,r][l,r]\to[l-1,r][l,r]→[l−1,r]可以效仿移动右端点的方式预处理RiR_iRi​以及gig_igi​即可。

时间复杂度O(nlog⁡n+nn)O(n\log n+n\sqrt{n})O(nlogn+nn​)

注意莫队首先移动右端点因为初始化时,l=1,r=0l=1,r=0l=1,r=0

#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
using pii=pair<int,int>;
using ll=long long;
constexpr int N=100010;
pii ST[N][22];
int lg[N];
int a[N],n,m;
int L[N],R[N],stk[N],top;
ll f[N],g[N];
int sz,pos[N];
void init(int n)
{lg[1]=0;for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;for(int i=1;i<=n;i++) ST[i][0]={a[i],i};for(int k=1;k<=lg[n];k++)for(int i=1;i+(1<<k)-1<=n;i++)  ST[i][k]=min(ST[i][k-1],ST[i+(1<<k-1)][k-1]);top=0;for(int i=1;i<=n;i++){while(top&&a[stk[top]]>a[i]) top--;L[i]=stk[top];stk[++top]=i;}stk[top=0]=n+1;for(int i=n;i>=1;i--){while(top&&a[stk[top]]>a[i]) top--;R[i]=stk[top];stk[++top]=i;}for(int i=1;i<=n;i++) f[i]=f[L[i]]+1ll*(i-L[i])*a[i];for(int i=n;i>=1;i--)g[i]=g[R[i]]+1ll*(R[i]-i)*a[i];sz=sqrt(n);for(int i=1;i<=n;i++) pos[i]=i/sz;}
int query(int l,int r)// [l,r]最小值的位置
{int k=lg[r-l+1];return min(ST[l][k],ST[r-(1<<k)+1][k]).second;
}
struct node
{int l,r;int id;bool operator<(const node&o)const{return pos[l]<pos[o.l]||pos[l]==pos[o.l]&&r<o.r;}
}q[N];
ll calcR(int l,int r)
{int p=query(l,r);return 1ll*a[p]*(p-l+1)+f[r]-f[p];
}
ll calcL(int l,int r)
{int p=query(l,r);return 1ll*a[p]*(r-p+1)+g[l]-g[p];
}
ll ans[N],res;
int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];init(n);for(int i=1;i<=m;i++){int l,r;cin>>l>>r;q[i]={l,r,i};}sort(q+1,q+1+m);int l=1,r=0;for(int i=1;i<=m;i++){while(r<q[i].r) res+=calcR(l,++r);//首先考虑右端点while(r>q[i].r) res-=calcR(l,r--);while(l<q[i].l) res-=calcL(l++,r);while(l>q[i].l) res+=calcL(--l,r);ans[q[i].id]=res;}for(int i=1;i<=m;i++) cout<<ans[i]<<'\n';return 0;
}

注意我改了2小时,对比代码才改出来,无语了~~~
要加油哦~

P3246 [HNOI2016]序列(莫队+单调栈+ST表)相关推荐

  1. 洛谷 - P3246 [HNOI2016]序列(莫队+单调栈)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,再给出 mmm 次询问,每次询问需要回答一个区间 [l,r][l,r][l,r] 内所有子区间的最小值之和 题目分析:因为可以离线,所以考 ...

  2. hdu6989 (莫队+单调栈+ST表)

    题意: 求l-r之间所有区间最大值最小值之和的期望,除法按照逆元来求; 题解: 看之前刚补的一道题目,那道题目跟这道题差不多,解释都在下面的链接中. [HNOI2016]序列 就是取余把人取傻了. # ...

  3. P3246 [HNOI2016]序列 莫队 + ST表 + 单调栈

    传送门 文章目录 题意: 思路: Update 题意: 思路: 比较神奇的一个题,这里先介绍莫队的离线解法. 不难发现,用莫队来做最大的难点就是在进行区间移动的时候如何快速计算贡献. 比如[l,r]− ...

  4. HDU - 6989 Didn‘t I Say to Make My Abilities Average in the Next Life?! 莫队/单调栈 + 线段树/ST表在线

    传送门 文章目录 题意: 思路: 题意: 思路: 考虑将贡献分开来算,先计算最大值,再算个最小值,之后答案就是((max+min)/2)/(len∗(len+1)/2)((max+min)/2)/(l ...

  5. 【BZOJ3956】Count,单调栈+ST表维护区间最大值

    Time:2016.08.11 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: TA爷眼中的水题 首先有个特别的结论 总共的点对数不会超过2n 因为对于元素i来说,如果只考虑与比它高 ...

  6. 【BZOJ】3956 Count 单调栈+ST表

    题目传送门 挺有思想的一题,但如果弄清楚了思路这题还是挺简单的. 首先我们可以发挥一下自己的脑洞,发现所有的好集对不可能相交. 那么我们可以刷两遍单调栈,求出每个点作为区间左端点或右端点的次数. 对于 ...

  7. P3246 [HNOI2016]序列(查询l-r中所有区间的最小值之和)

    多校时做到了查询区间l-r中所有区间的最大值与最小之和的题目,有好多细节不太会处理,去看题解发现是一道差不多的原题,于是打算先把原题补一下. 题解: ST表+单调栈+莫队 看到计算区间最小值之和,不难 ...

  8. [BZOJ4542] [Hnoi2016] 大数 (莫队)

    Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345 .小B还有一个素数P.现在,小 B 提出了 M 个询问,每 ...

  9. 4542: [Hnoi2016]大数|莫队

    HN一天考两个莫队是什么鬼..或者说莫队不是正确的姿势..? 考虑已经知道了 l..r l..r的答案新添入 r+1 r+1如何更新当前答案 需要先预处理出后缀 modp mod p的值 bi b_i ...

最新文章

  1. 算力觉醒后,智慧距离勃发就只差一个想法
  2. android StringBuffer实现换行
  3. html基于web2.0标准,晕倒:“用web2.0来制作符合标准的页面”
  4. python判断文件是否存在 中文_python如何判断文件是否存在
  5. idea 自动导入包操作及快捷键
  6. 专注创新勇突破 宏杉科技七策定纲存储之道
  7. 【Flash动画制作】
  8. java云之家发送信息_开发文档:考勤信息api - 云之家·开放平台
  9. python——algorithms模块
  10. 考研英语阅读12种解题技巧!码住!
  11. Unity Shader 实现简单的压扁效果
  12. POS接口与GE接口区别
  13. 胡喜:从 BASIC 到 basic ,蚂蚁金服技术要解决两个基本的计算问题
  14. 你是资讯控吗?——Web2.0智识管理简册
  15. eclipse中的javaEE插件
  16. 计网PPT 第九章 无线网络和移动网络
  17. Post请求报错405
  18. JavaScript大集合笔记
  19. 那些年,我们曾白嫖到的图床
  20. 163音乐点歌乱码分析以及解决办法

热门文章

  1. oracle 12c 多线程,Oracle 12c(12.1)中性能优化功能增强之通过参数THREADED_EXECTION使用多线程模型...
  2. linux多内核调度,linux-kernel – 如何在Linux内核(Samsung Exynos5422)中实现异构多处理(HMP)调度?...
  3. 问题 C: 【例2-3】围圈报数
  4. [JavaWeb-MySQL]多表查询概述
  5. [C++11]decltype在泛型编程中的使用举例
  6. C++实现线段树RMQ-单点修改,区间查询
  7. 高等数学上-赵立军-北京大学出版社-题解-练习4.5
  8. 多重背包问题以及二进制优化
  9. java调优方法,jvm监控工具
  10. redis持久化到mysql的方案_redis进阶: 数据持久化