BZOJ 4540 [Hnoi2016]序列 (单调栈 + ST表 + 莫队算法)
题目链接 BZOJ4540
考虑莫队算法。
这题难在$[l, r]$到$[l, r+1]$的转移。
根据莫队算法的原理,这个时候答案应该加上
$cal(l, r+1) + cal(l+1, r+1) + cal(l+2, r+1) + ... + cal(r+1, r+1)$
$cal(l, r)$表示$a[l], a[l+1], a[l+2], ..., a[r]$中的最小值。
我们先求出$[l, r +1]$ 这些数中的最小值$a[x]$
那么$cal(l, r+1) + cal(l+1, r+1) + cal(l+2, r+1) + ... + cal(x, r+1)$这一部分就解决了
这一部分的值为$(x - l + 1) * a[x]$
剩下还有一部分$cal(x+1, r+1) + cal(x+2, r+1) + ... + cal(r+1, r+1)$
考虑用单调栈求出两个数组$lc[], rc[]$。
$lc[i]$表示$a[i]$左边第一个小于$a[i]$的数的位置(如果没有则为$0$)
$rc[i]$表示$a[i]$右边第一个小于$a[i]$的数的位置(如果没有则为$n+1$)
然后我们维护两个序列$s1[], s2[]$
$s1[i] = s1[lc[i]] + (i - lc[i]) * a[i]$
刚刚那个剩余的情况中,$s1[r+1] - s1[x]$即为这部分的答案。
因为满足$a[r+1]>=a[x]$,所以对于$a[r+1]$来说,他往左不断找第一个小于他的数,
肯定能在某一步找到$a[x]$.
而我们维护$s1[]$的目的就是把这个跳的过程做到$O(1)$.
转移就是这样
那么另外三种情况也差不多,以此类推。
时间复杂度$O(n^{\frac{3}{2}}logn)$
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = 1e5 + 10;
const int A = 20; int n, m;
int lc[N], rc[N], lg[N], belong[N];
int f[N][A];
int bs, l, r, x;
stack <int> s;
LL ans;
LL a[N];
LL s1[N], s2[N];
LL ret[N]; struct node{
int l, r, id;
friend bool operator < (const node &a, const node &b){
return belong[a.l] == belong[b.l] ? a.r < b.r : belong[a.l] < belong[b.l];
}
} q[N]; inline int Min(int x, int y){ return a[x] < a[y] ? x : y;} void ST(){
rep(i, 1, n) f[i][0] = i;
rep(j, 1, 18) rep(i, 1, n)
if ((i + (1 << j) - 1) <= n) f[i][j] = Min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
} inline int solve(int l, int r){
int k = lg[r - l + 1];
return Min(f[l][k], f[r - (1 << k) + 1][k]);
} int main(){ rep(i, 2, 1e5) lg[i] = lg[i >> 1] + 1; scanf("%d%d", &n, &m);
rep(i, 1, n) scanf("%lld", a + i); ST();
rep(i, 1, n){
while (!s.empty() && a[s.top()] >= a[i]) s.pop();
if (s.empty()) lc[i] = 0;
else lc[i] = s.top();
s.push(i);
} while (!s.empty()) s.pop();
dec(i, n, 1){
while (!s.empty() && a[s.top()] >= a[i]) s.pop();
if (s.empty()) rc[i] = n + 1;
else rc[i] = s.top();
s.push(i);
} rep(i, 1, n) s1[i] = s1[lc[i]] + (i - lc[i]) * a[i];
dec(i, n, 1) s2[i] = s2[rc[i]] + (rc[i] - i) * a[i]; bs = sqrt(n);
rep(i, 1, n) belong[i] = (i - 1) / bs + 1; rep(i, 1, m){
scanf("%d%d", &q[i].l, &q[i].r);
q[i].id = i;
} sort(q + 1, q + m + 1);
l = 1, r = 0, ans = 0;
rep(i, 1, m){
while (r < q[i].r){
++r;
x = solve(l, r);
ans += ((x - l + 1) * a[x] + s1[r] - s1[x]);
} while (r > q[i].r){
x = solve(l, r);
ans -= ((x - l + 1) * a[x] + s1[r] - s1[x]);
--r;
} while (l > q[i].l){
--l;
x = solve(l, r);
ans += ((r - x + 1) * a[x] + s2[l] - s2[x]);
} while (l < q[i].l){
x = solve(l, r);
ans -= ((r - x + 1) * a[x] + s2[l] - s2[x]);
++l;
} ret[q[i].id] = ans;
} rep(i, 1, m) printf("%lld\n", ret[i]);
return 0;
}
BZOJ 4540 [Hnoi2016]序列 (单调栈 + ST表 + 莫队算法)的更多相关文章
- BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]
4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ...
- BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)
BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...
- [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 ...
- bzoj 4540: [Hnoi2016]序列【单调栈+线段树】
强烈安利:http://blog.csdn.net/qq_34637390/article/details/51313126 这篇讲标记讲的非常好,这个标记非常神奇-- 首先last表示扫描到last ...
- BZOJ 4540 [Hnoi2016]序列 | 莫队 详细题解
传送门 BZOJ 4540 题解 --怎么说呢--本来想写线段树+矩阵乘法的-- --但是嘛--yali的机房太热了--困--写不出来-- 于是弃疗,写起了莫队.(但是我连莫队都想不出来!) 首先用单 ...
- BZOJ3879:SvT(后缀数组,单调栈,ST表)
Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始 ...
- Max answer(单调栈+ST表)
Max answer https://nanti.jisuanke.com/t/38228 Alice has a magic array. She suggests that the value o ...
- BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】
题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...
- bzoj3956: Count (单调栈+st表)
题面链接 bzoj 题解 非常巧妙的一道题 类似[hnoi影魔] 每个点会给左右第一个大于它的点对产生贡献 可以用单调栈求出 这里有点小细节,就是处理相等的点时,最左边的点管左边的贡献,最右边的点管最 ...
随机推荐
- 下载旧版本的JDK
下载旧版本的JDK 有的时候我们需要去下载旧版本的JDK,但是进入Oracle官网,显示的总是新版的JDK,这里告诉大家怎么样去下载旧版本的JDK. 首先去JavaSE的 下载界面 拉到最下面,找到这 ...
- DP刷题记录(长期更新)
bzoj 2748 一个吉他手,有一个初始音量,有一个音量最大值max. 给定n个音量变化量,从第一个变化量开始,可以选择加上或者减去变化量.途中音量不能低于0,不能超过max. 求最后能达到的最大音 ...
- Linux学习-SELinux 初探
什么是 SELinux 什么是 SELinux 呢?其实他是『 Security Enhanced Linux 』的缩写,字面上的意义就是安全强化的 Linux 之意! 当初设计的目标:避免资源的误用 ...
- kettle-批量同步表数据
一.实验目标 利用kettle实现从mysql数据库中的dbf库批量同步表到dbm库(全量同步) 二.实验环境 dbf 库中表f1.f2.f3 .f1中1条数据,f2中100条数据,f3中2条数据 ...
- hdu4489 组合公式+dp
这里对于题意在说明一下, 题目中要求的排列必须是波浪形,每一个在排列中的人不是波峰就是波谷,如果它既不是波峰也不是波谷排列就是错的. 对于我这种数学渣渣来说,做一道dp题要好久,%>_<% ...
- python 模块相互import
模块A中import B,而在模块B中import A.这时会怎么样呢?这个在Python列表中由RobertChen给出了详细解释,抄录如下: [A.py] from B import D clas ...
- 回调深入理解 同步回调 以android中View.OnClickListener为列
现在来分析分析下Android View的点击方法onclick();我们知道onclick()是一个回调方法,当用户点击View就执行这个方法,我们用Button来举例好了 //这个是View的 ...
- configurationChanges
在Android中每次屏幕的切换动会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次Create的时候载入配置.在activity加上android:c ...
- 关于.net 项目 nuget包还原项目失败的记录
在.net项目中,一般通过vs打开项目,会自动进行nuget包还原,可能因为其他一些因素,包还原失败,同时在之前包依赖是可以正常使用,现在却提示包 AutoMapper 6.2.2 与 netcore ...
- PTA 11-散列4 Hard Version (30分)
题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/680 5-18 Hashing - Hard Version (30分) Given ...