4540: [Hnoi2016]序列

https://www.lydsy.com/JudgeOnline/problem.php?id=4540

分析:

  莫队+RMQ+单调栈。

  考虑加入一个点后,区间发生了什么变化。[l,r]->[l,r+1],增加了r-l+1段区间。设[l,r+1]的最小值在p,那么左端点在l~p-1的区间,答案就是a[p]了,p右边同样还存在许多最小值,影响了一段的区间。

  每个点影响的区间是这样的,p的贡献就是a[p]*(p-l+1),剩余的贡献,可以记录每个位置向左的前缀和,那么求出p+1~R+1的贡献就行了(L可能不是最小的点,不能直接算L~R+1,只能从p开始算,p剩余的部分,单独算了)。同样的向右的也是这样求出。用单调栈求出每个位置左边第一个比它大的L[i],然后sl[i] = sl[L[i]] + a[i] * (i - L[i])。快速求出最小的值得位置的过程可以用RMQ维护。

  于是就可以开心的用莫队了。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; int a[N], sk[N], bel[N], L[N], R[N], f[N][], Log[N];
LL ans[N], sl[N], sr[N], Answer;
struct Que{
int l, r, id;
bool operator < (const Que &A) const {
return bel[l] == bel[A.l] ? r < A.r : bel[l] < bel[A.l];
}
}q[N]; inline int Min(int i,int j) {
return a[i] < a[j] ? i : j;
}
inline int Calc(int l,int r) {
if (r < l) swap(l, r);
int t = Log[r - l + ];
return Min(f[l][t], f[r - ( << t) + ][t]);
}
inline void updl(int l,int r,int o) {
int p = Calc(l, r);
LL t = 1ll * a[p] * (r - p + ) + sr[l] - sr[p];
Answer += o * t;
}
inline void updr(int l,int r,int o) {
int p = Calc(l, r);
LL t = 1ll * a[p] * (p - l + ) + sl[r] - sl[p];
Answer += o * t;
}
int main() { fi("1.txt");
int n = read(), Q = read(), B = sqrt(n); Log[] = -;
for (int i=; i<=n; ++i) {
a[i] = read();
bel[i] = (i - ) / B + ;
Log[i] = Log[i >> ] + ;
f[i][] = i;
}
for (int i=; i<=Q; ++i)
q[i].l = read(), q[i].r = read(), q[i].id = i; for (int j=; j<=Log[n]; ++j)
for (int i=; i+(<<j)-<=n; ++i)
f[i][j] = Min(f[i][j - ], f[i + ( << (j - ))][j - ]); int top = ;
for (int i=; i<=n; ++i) {
while (top && a[sk[top]] >= a[i]) R[sk[top]] = i, top --;
sk[++top] = i;
}
while (top) R[sk[top]] = n + , top --;
for (int i=n; i>=; --i) {
while (top && a[sk[top]] > a[i]) L[sk[top]] = i, top --;
sk[++top] = i;
}
while (top) L[sk[top]] = , top --; for (int i=; i<=n; ++i) sl[i] = sl[L[i]] + 1ll * (i - L[i]) * a[i];
for (int i=n; i>=; --i) sr[i] = sr[R[i]] + 1ll * (R[i] - i) * a[i]; sort(q + , q + Q + );
int l = , r = ;
for (int i=; i<=Q; ++i) {
while (l > q[i].l) l --, updl(l, r, ); // 先加在减!!!
while (r < q[i].r) r ++, updr(l, r, );
while (l < q[i].l) updl(l, r, -), l ++;
while (r > q[i].r) updr(l, r, -), r --;
ans[q[i].id] = Answer;
}
for (int i=; i<=Q; ++i)
printf("%lld\n", ans[i]);
return ;
}

4540: [Hnoi2016]序列的更多相关文章

  1. BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]

    4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ...

  2. BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)

    BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...

  3. BZOJ 4540 [Hnoi2016]序列 | 莫队 详细题解

    传送门 BZOJ 4540 题解 --怎么说呢--本来想写线段树+矩阵乘法的-- --但是嘛--yali的机房太热了--困--写不出来-- 于是弃疗,写起了莫队.(但是我连莫队都想不出来!) 首先用单 ...

  4. bzoj 4540: [Hnoi2016]序列

    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,则称 ...

  5. bzoj 4540: [Hnoi2016]序列 莫队

    题目: 给定长度为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[s:t]是a ...

  6. BZOJ 4540 [Hnoi2016]序列 (单调栈 + ST表 + 莫队算法)

    题目链接  BZOJ4540 考虑莫队算法. 这题难在$[l, r]$到$[l, r+1]$的转移. 根据莫队算法的原理,这个时候答案应该加上 $cal(l, r+1) + cal(l+1, r+1) ...

  7. bzoj 4540: [Hnoi2016]序列【单调栈+线段树】

    强烈安利:http://blog.csdn.net/qq_34637390/article/details/51313126 这篇讲标记讲的非常好,这个标记非常神奇-- 首先last表示扫描到last ...

  8. [BZOJ4540][HNOI2016]序列 莫队

    4540: [Hnoi2016]序列 Time Limit: 20 Sec  Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ...

  9. [Bzoj4540][Hnoi2016] 序列(莫队 + ST表 + 单调队列)

    4540: [Hnoi2016]序列 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1567  Solved: 718[Submit][Status] ...

随机推荐

  1. 寄存器简介 与 ebp esp

    http://www.cnblogs.com/zhuyuanhao/archive/2012/10/16/3262870.html 32位CPU所含有的寄存器有:4个数据寄存器(EAX.EBX.ECX ...

  2. MFC窗体程序中添加调试控制台

    在编写复杂程序的过程中,我们经常需要将一些信息输出到文件或者屏幕上.较控制台应用程序,MFC窗体程序要显得麻烦一些! 下面有2种方法来实现为MFC窗体程序添加调试控制台,方便程序员调试程序和了解当前程 ...

  3. 利用maven开发springMVC项目(二)——框架配置

    申明:主要内容来源于大神博客(使用IntelliJ IDEA开发SpringMVC网站(二)框架配置),我只是用eclipse自己练习使用,记录下来也只是为了学习使用,没有任何的商业用途,侵权必删. ...

  4. PAT——1072. 开学寄语(20)

    下图是上海某校的新学期开学寄语:天将降大任于斯人也,必先删其微博,卸其QQ,封其电脑,夺其手机,收其ipad,断其wifi,使其百无聊赖,然后,净面.理发.整衣,然后思过.读书.锻炼.明智.开悟.精进 ...

  5. [LuoguP1360][USACP07MAR]黄金阵容均衡

    [LuoguP1360][USACP07MAR]黄金阵容均衡(Link) 每天会增加一个数\(A\),将\(A\)二进制分解为\(a[i]\),对于每一个\(i\)都增加\(a[i]\),如果一段时间 ...

  6. Java性能监控

    Java性能监控 上次介绍了如何使用jvisualvm监控java,今天做进一步讲解!Java性能监控主要关注CPU.内存和线程. 在线程页中,点击线程Dump,可以生成threaddump日志,通过 ...

  7. 用JavaScript编写气泡

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 【CSS3基础-Flex布局】

    关于Flex 背景 在flex布局出现以前,常用的水平和垂直居中对齐方式有很多.flex布局的出现基本规范了这一过程. 通过justify-content和align-items两个属性即解决了水平居 ...

  9. .Net core 使用NPOI 直接导入Excel到数据库(即不先将Excel保存到服务器再读取文件到数据库)

    /// <summary> /// 导入信息 /// </summary> /// <param name="file"></param& ...

  10. Linux-- 文件编辑器 vi/vim(1)

    初识 vi/vim 文本编辑器 1.vi 和 vim 相同,都是文本编辑器,在 vi 模式下可以查看文本,编辑文本,是 Linux 最常用的命令,vi 模式下分为三部分,第一部分一般模式,在一般模式中 ...