【LG3246】[HNOI2016]序列

题面

洛谷

题解

60pts

对于每个位置\(i\),单调栈维护它往左第一个小于等于它的位置\(lp_i\)以及往右第一个小于它的位置\(rp_i\)。

那么在左端点在\((lp_i,i]\),右端点在\([i,rp_i)\)的所有区间中,

区间的贡献均为\(a_i\)(之所以取等情况不一样是防止算重或算漏)。

那么对于一个询问\(L,R\),有

\[Ans=\sum_{i=L}^R (i-max(lp_i+1,L)+1)\cdot (min(rp_i-1,R)-i+1)
\]

100pts

考虑莫队,那么我们的难点主要就是怎么从区间\([L,R]\)转移到区间\([L,R+1]\)。

用ST表查一下\([L,R+1]\)的最小值的位置\(p\),则左端点在\([L,p]\)的区间贡献均为\(a[p]\)。

现在考虑左端点在\([p+1,R+1]\)的贡献,记一个类似于前缀和的东西\(f_i=f_{lp_i}+(i-lp_i)*a[i]\),

则可以算出区间\([p+1,R+1]\)的贡献为\(f_{R+1}-f_p\),因为\(f_i\)相当于求\(i\)的\(lp\),它\(lp\)的\(lp\)...

到\(i\)的贡献,而\(p\)必为某一个转移端点,所以成立。

向\([L-1,R]\)转移同样维护一个\(g_i=g_{rp_i}+(rp_i-i)*a[i]\)。

减法直接减去一个位置对区间的贡献即可。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
typedef long long ll;
const int MAX_N = 1e5 + 5;
const int LEN = 320;
int N, Q, a[MAX_N], bel[MAX_N];
struct Query { int l, r, id; } q[MAX_N], tmp[MAX_N];
bool operator < (const Query &lhs, const Query &rhs) {
if (bel[lhs.l] == bel[rhs.l]) return (bel[lhs.l] & 1) ? lhs.r < rhs.r : lhs.r > rhs.r;
else return bel[lhs.l] < bel[rhs.l];
}
int stk[MAX_N], top, lp[MAX_N], rp[MAX_N];
int st[18][MAX_N], bin[18], lg[MAX_N];
int query(int l, int r) {
int k = lg[r - l + 1];
if (a[st[k][l]] < a[st[k][r - bin[k] + 1]]) return st[k][l];
else return st[k][r - bin[k] + 1];
}
ll L[MAX_N], R[MAX_N], ans[MAX_N], Ans;
ll Ladd(int l, int r) {
int p = query(l - 1, r);
return 1ll * a[p] * (r - p + 1) + R[l - 1] - R[p];
}
ll Radd(int l, int r) {
int p = query(l, r + 1);
return 1ll * a[p] * (p - l + 1) + L[r + 1] - L[p];
} int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
freopen("cpp.out", "w", stdout);
#endif
N = gi(), Q = gi();
for (int i = 1; i <= N; i++) a[i] = gi();
for (int i = 1; i <= N; i++) bel[i] = (i - 1) / LEN + 1;
bin[0] = 1; for (int i = 1; i <= 17; i++) bin[i] = bin[i - 1] << 1;
for (int i = 2; i <= N; i++) lg[i] = lg[i >> 1] + 1;
for (int i = 1; i <= N; i++) st[0][i] = i;
for (int i = 1; bin[i] <= N; i++)
for (int j = 1; j + bin[i] - 1 <= N; j++)
if (a[st[i - 1][j]] < a[st[i - 1][j + bin[i - 1]]]) st[i][j] = st[i - 1][j];
else st[i][j] = st[i - 1][j + bin[i - 1]];
for (int i = 1; i <= Q; i++) {
int l = gi(), r = gi();
q[i] = (Query){l, r, i};
}
sort(&q[1], &q[Q + 1]);
stk[0] = 0;
for (int i = 1; i <= N; i++) {
while (a[stk[top]] >= a[i] && top) --top;
lp[i] = stk[top], stk[++top] = i;
}
top = 0, stk[0] = N + 1;
for (int i = N; i >= 1; i--) {
while (a[stk[top]] > a[i] && top) --top;
rp[i] = stk[top], stk[++top] = i;
}
for (int i = 1; i <= N; i++) L[i] = L[lp[i]] + 1ll * (i - lp[i]) * a[i];
for (int i = N; i >= 1; i--) R[i] = R[rp[i]] + 1ll * (rp[i] - i) * a[i];
int ql = 1, qr = 0;
for (int i = 1; i <= Q; i++) {
while (qr < q[i].r) ++qr, Ans += Radd(ql, qr - 1);
while (ql < q[i].l) Ans -= Ladd(ql + 1, qr), ++ql;
while (ql > q[i].l) --ql, Ans += Ladd(ql + 1, qr);
while (qr > q[i].r) Ans -= Radd(ql, qr - 1), --qr;
ans[q[i].id] = Ans;
}
for (int i = 1; i <= Q; i++) printf("%lld\n", ans[i]);
return 0;
}

【LG3246】[HNOI2016]序列的更多相关文章

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

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

  2. 4540: [Hnoi2016]序列

    4540: [Hnoi2016]序列 https://www.lydsy.com/JudgeOnline/problem.php?id=4540 分析: 莫队+RMQ+单调栈. 考虑加入一个点后,区间 ...

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

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

  4. BZOJ4540 Hnoi2016 序列 【莫队+RMQ+单调栈预处理】*

    BZOJ4540 Hnoi2016 序列 Description 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- ...

  5. 【BZOJ4540】[Hnoi2016]序列 莫队算法+单调栈

    [BZOJ4540][Hnoi2016]序列 Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,a ...

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

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

  7. [HNOI2016]序列 CDQ+DP

    [HNOI2016]序列 CDQ 链接 loj 思路 一个点最小变为l,最大变为r,不变的时候为v 那么j能在i前面就要满足. \(j<i\) \(r[j]<=v[i]\) \(v[j]& ...

  8. 题解-[HNOI2016]序列

    题解-[HNOI2016]序列 [HNOI2016]序列 给定 \(n\) 和 \(m\) 以及序列 \(a\{n\}\).有 \(m\) 次询问,每次给定区间 \([l,r]\in[1,n]\),求 ...

  9. P6604 [HNOI2016]序列 加强版

    *I. P6604 [HNOI2016]序列 加强版 摘自学习笔记 简单树论 笛卡尔树部分例题 I. 和 P6503 比较类似.我们设 \(f_i\) 表示全局以 \(i\) 结尾的子区间的最小值之和 ...

随机推荐

  1. CVE-2013-2551漏洞成因与利用分析(ISCC2014 PWN6)

    CVE-2013-2551漏洞成因与利用分析 1. 简介 VUPEN在Pwn2Own2013上利用此漏洞攻破了Win8+IE10,5月22日VUPEN在其博客上公布了漏洞的细节.它是一个ORG数组整数 ...

  2. oracle PL/SQL调用Java生成Excel

    现在有个需求,  要求编写oracle存储过程生成Excel文件到指定目录,  但是oracle自己的API貌似不太给力,  所以只能通过另一种更强大的语言来实现了  ——Java.有一个Java框架 ...

  3. shell study

    目录 shell记录 执行脚本 变量使用 注释 shell传递参数 运算符 echo printf test 流程控制 if ... else ... for while until case 跳出循 ...

  4. ansible.md

    ansible 测试环境配置 注意:192.168.100.201这台机器是主控机,剩下的192.168.100.202.192.168.100.203.192.168.100.210均为测试主机. ...

  5. 是否含有RTTI(运行时类型信息)是动态语言与静态语言的主要区别

    运行时类型信息代表类型信息和对内存的操作能力. 运行时类型信息是运行时系统的基础. 类型信息分为编译时类型信息和运行时类型信息两种: 静态语言的类型信息只在编译时使用和保留,在可执行文件中没有类型信息 ...

  6. 20165318 2017-2018-2 《Java程序设计》第六周学习总结

    20165318 2017-2018-2 <Java程序设计>第六周学习总结 教材内容学习总结 第八章 常用实用类 1.String类 String类用来处理字符序列,在java.lang ...

  7. 【洛谷】【线段树+位运算】P2574 XOR的艺术

    [题目描述:] AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏.在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下 1. 拥有一个伤害串为长度为n的01串. 2. 给定一个范围[ ...

  8. weblogic之CVE-2018-3246 XXE分析

    通过ftp通道将数据传出来.上传1.xml <!DOCTYPE xmlrootname [<!ENTITY % aaa SYSTEM "http://192.168.172.12 ...

  9. docker 导入导出镜像

    docker容器导入导出有两种方法: 一种是使用save和load命令 使用例子如下: docker save ubuntu:load>/root/ubuntu.tar docker load& ...

  10. ethers.js-2-wallets and signers

    Application Programming Interface (API) Wallets and Signers A Wallet manages a private/public key pa ...