loj #2051. 「HNOI2016」序列(莫队+ST+单调栈)
来源:互联网 发布:windows loader 和kms 编辑:程序博客网 时间:2024/06/07 01:44
题目链接
#2051. 「HNOI2016」序列
求
分析
又是区间查询,上莫队了.首先想[l,r]-> [l,r+1] 它的增量是多少.
设[l,r+1] 的最小值的位置是
设
sl[i] 表示以i 为右端点的所有区间的贡献前缀和,那么显然当前区间中r+1 为右端点的贡献为sl[r+1]−sl[p]
记
l[i] : 左边第一个比a[i] 严格小的位置
r[i] : 右边第一个小于等于a[i] 的位置
那么显然
sl[i]=sl[l[i]]+a[i]∗(i−l[i])
因此用单调栈预处理l[i],r[i] ,然后用ST表查询最小值的位置就好了
中途WA了很多次,原来莫队更新的顺序很重要,特别是与区间相关,点不独立的问题
AC code
#include <bits/stdc++.h>using namespace std;#define ms(x,v) (memset((x),(v),sizeof(x)))#define pb push_back#define mp make_pair#define fi first#define se secondtypedef long long LL;typedef pair<int,int > Pair;const int maxn = 1e5+10;int n,m;LL a[maxn];const int S = 300;struct Query{ int l,r,id; bool operator < (const Query & o)const{ return l/S == o.l/S?r < o.r:l<o.l; }};Query q[maxn];int l[maxn],r[maxn],stk[maxn],top;LL sl[maxn],sr[maxn],ret[maxn];void init() { top=0; for(int i=1 ; i<=n ; ++i){ while (top && a[stk[top]] >=a[i])r[stk[top--]] =i;//被右端第一个小于等于它的元素驱逐出栈 stk[++top] =i; } top=0; for(int i=n ; i>0 ; --i){ while (top && a[stk[top]] > a[i])l[stk[top--]] = i; stk[++top] = i; } sl[0] = 0;sr[n+1] = 0;l[1] =0;r[n] = n+1; for(int i=1 ; i<=n ; ++i)sl[i] = sl[l[i]]+(LL)a[i]*(i-l[i]); for(int i=n ; i>0 ; --i)sr[i] = sr[r[i]] + (LL)a[i]*(r[i]-i);}namespace ST{ int st[maxn][22],lg2[maxn]; void init_rmq(int n,LL a[]) { lg2[0] =-1; for(int i=1 ; i<=n ; ++i){ lg2[i] = ((i&(i-1)) == 0)?lg2[i-1]+1:lg2[i-1]; st[i][0] =i; } for(int j=1 ; j<=lg2[n]; ++j) for(int i=1 ; i+(1<<j)-1 <=n ; ++i) st[i][j] = (a[st[i][j-1]]<a[st[i+(1<<(j-1))][j-1]])?st[i][j-1]:st[i+(1<<(j-1))][j-1]; } int rmq(int l,int r,LL a[]){ int k = lg2[r-l+1]; return a[st[l][k]] < a[st[r-(1<<k)+1][k]]?st[l][k]:st[r-(1<<k)+1][k]; }};using namespace ST;inline LL moveL(int l,int r) { int p = rmq(l,r,a); return sr[l]-sr[p]+a[p]*(r-p+1);}inline LL moveR(int l,int r){ int p = rmq(l,r,a); return sl[r] - sl[p]+a[p]*(p-l+1);}int main(){ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin>>n>>m; for(int i=1 ; i<=n ; ++i)cin>>a[i]; init_rmq(n,a); init(); for(int i=0 ; i<m ; ++i){ q[i].id = i;cin>>q[i].l >> q[i].r; } sort(q,q+m); int curL=q[0].l,curR = q[0].l-1; LL ans =0; for(int i=0 ; i<m ; ++i){ int L = q[i].l,R = q[i].r; while (curR < R)ans += moveR(curL,++curR); while (curL > L)ans += moveL(--curL,curR); while (curR > R)ans -= moveR(curL,curR--); while (curL < L)ans -=moveL(curL++,curR); ret[q[i].id] = ans; } for(int i=0 ; i<m ; ++i)std::cout << ret[i] << '\n'; return 0;}
阅读全文
0 0
- loj #2051. 「HNOI2016」序列(莫队+ST+单调栈)
- bzoj4540 [Hnoi2016]序列 (莫队+ST表+单调栈)
- bzoj 4540: [Hnoi2016]序列 (莫队+ST表+单调栈|线段树)
- loj #2053. 「HNOI2016」大数(莫队)
- [莫队 单调栈] BZOJ 4540 [Hnoi2016]序列
- 4540: [Hnoi2016]序列|莫队+ST表
- 【bzoj4540】【HNOI2016】【序列】【莫队+st表】
- HNOI2016 序列(sequence)<莫队>
- Bzoj4540:[Hnoi2016]序列:莫队+RMQ
- BZOJ 4542([Hnoi2016]序列-莫队)
- [bzoj4540][Hnoi2016]序列 莫队+RMQ
- 【HNOI2016】序列
- [矩阵乘法] LOJ#2002. 「SDOI2017」序列计数
- poj 2796 st算法+二分 / 单调栈
- 【BZOJ】3956 Count 单调栈+ST表
- bzoj4540: [Hnoi2016]序列
- bzoj4540: [Hnoi2016]序列
- BZOJ4540 HNOI2016 序列
- 三菱数控CNC系统G代码M代码大全
- 读书笔记---Explain Images with Multimodal Recurrent Neural Networks
- oracle知识总结
- 从零开始···require.js加载css文件插件require-css
- 【Java团队用OpenResty】2、Eclipse开发环境搭建
- loj #2051. 「HNOI2016」序列(莫队+ST+单调栈)
- LeetCode 513. Find Bottom Left Tree Value
- 在Keras 和 Tensorflow 框架下五种视频分类的实施方法
- 将类数组转换成数组封装成方法
- 游戏裁剪
- C#struct结构体
- redis 对key的设置操作
- Spring Aop实例之xml配置
- 将jenkins部署到tomcat上,使用tomcat启动和关闭