LOJ 6057 - [HNOI2016]序列 加强版再加强版
Description
给定一个长度为 \(n\le 3*10^6\) 的序列
\(q\le 10^7\) 次询问每次求区间 \([l,r]\) 的所有子区间的最小值的和
询问随机
Solution
考虑求出区间的最小值, 设在位置 \(p\)
考虑 \([l, p)\) 和 \((p, r]\) 的答案
\([l, p) = [l, n] - [p, n] - (左端点在[l, p) 右端点在[p, n] 的)\)
因为 \([l, p)\) 都比 \(p\) 小
所以该部分为 \((p-l) * 左端点在p的答案\)
区间最小值可以用rmq求
正常的O(n)-O(1) rmq需要转成树, 然后变成 \(\pm 1\) 的, 然后分块块内还要预处理, 常数很大
注意到这题询问随机, 询问到块内的几率很小, 所以可以把块内的处理改成暴力
块边缘维护前后缀min即可
Code
#include <bits/stdc++.h>
using namespace std;
#define ri rd<int>
#define rep(i, a, b) for (int i = (a), _ = (b); i <= _; ++i)
#define per(i, a, b) for (int i = (a), _ = (b); i >= _; --i)
#define For(i, a, b) for (int i = (a), _ = (b); i < _; ++i)
const int maxN = 3e6 + 7;
const int INF = 1e9 + 7;
typedef long long LL;
const LL O = 1e9 + 7;
template<class T> T rd() {
bool f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = 0;
T x = 0; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return f ? x : -x;
}
int n, m;
int a[maxN];
namespace IO {
int A, B, C, P;
LL lastAns;
inline int rnd() {
return A = (A * B + (C ^ (int)(lastAns & 0x7fffffffLL)) % P) % P;
}
void init() {
A = ri(), B = ri(), C = ri(), P = ri();
lastAns = 0;
}
}
namespace RMQ {
const int maxL = 3e5 + 7;
const int B = 12;
struct Node {
int l, r, v;
int pre[12], suf[12];
}a[maxL];
int st[maxL][20];
int ln[maxL];
int bl[maxN];
void gmin(int &x, int y) {
if (::a[y] < ::a[x]) x = y;
}
int ggmin(int x, int y) {
return ::a[x] < ::a[y] ? x : y;
}
void init() {
rep (i, 1, n) {
int &t = bl[i] = i / B;
int &v = st[t][0];
if (a[t].l == 0) {
a[t].l = i;
v = i;
}
a[t].r = i;
gmin(v, i);
}
int T = bl[n];
rep (j, 0, T) {
Node &t = a[j];
int l = t.l, r = t.r;
t.pre[0] = l;
rep (i, l+1, r) t.pre[i-l] = ggmin(t.pre[i-l-1], i);
t.suf[0] = r;
per (i, r-1, l) t.suf[r-i] = ggmin(t.suf[r-i-1], i);
}
rep (i, 2, T) ln[i] = ln[i >> 1] + 1;
per (i, T, 0) {
rep (j, 1, ln[T-i+1])
st[i][j] = ggmin(st[i][j-1], st[i+(1<<(j-1))][j-1]);
}
}
int eval(int l, int r) {
int len = ln[r-l+1];
return ggmin(st[l][len], st[r-(1<<len)+1][len]);
}
int get(int l, int r) {
int res = l;
if (bl[l] == bl[r]) {
rep (i, l, r) gmin(res, i);
return res;
}
int u = bl[l], v = bl[r];
gmin(res, a[u].suf[a[u].r - l]);
gmin(res, a[v].pre[r - a[v].l]);
if (u+1 < v) gmin(res, eval(u+1, v-1));
return res;
}
}
namespace Solve {
LL pre[maxN], suf[maxN];
void init() {
static int stack[maxN], Top;
stack[Top = 0] = 0;
LL res = 0;
rep (i, 1, n) {
for (; Top && a[stack[Top]] >= a[i]; --Top)
res -= 1LL * a[stack[Top]] * (stack[Top] - stack[Top-1]);
stack[++Top] = i;
res += 1LL * a[i] * (stack[Top] - stack[Top-1]);
pre[i] = res;
}
res = 0;
per (i, n, 1) {
for (; Top && a[stack[Top]] >= a[i]; --Top)
res -= 1LL * a[stack[Top]] * (stack[Top-1] - stack[Top]);
stack[++Top] = i;
res += 1LL * a[i] * (stack[Top-1] - stack[Top]);
suf[i] = res;
}
rep (i, 1, n) pre[i] += pre[i-1];
per (i, n, 1) suf[i] += suf[i+1];
}
LL getr(int l, int r) {
return suf[l] - suf[r] - 1LL * (r-l) * (suf[r] - suf[r+1]);
}
LL getl(int l, int r) {
return pre[r] - pre[l] - 1LL * (r-l) * (pre[l] - pre[l-1]);
}
}
LL get(int l, int r) {
int p = RMQ::get(l, r);
LL res = 1LL * (p-l+1) * (r-p+1) * a[p];
if (l < p) res += Solve::getr(l, p);
if (p < r) res += Solve::getl(p, r);
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("a.in", "r", stdin);
#endif
n = ri(), m = ri();
rep (i, 1, n) a[i] = ri();
IO::init();
RMQ::init();
Solve::init();
LL res = 0;
rep (i, 1, m) {
int l = IO::rnd() % n + 1, r = IO::rnd() % n + 1;
if (l > r) std::swap(l, r);
LL &tp = IO::lastAns = get(l, r);
res += tp % O;
}
printf("%lld\n", (res % O + O) % O);
return 0;
}
LOJ 6057 - [HNOI2016]序列 加强版再加强版的更多相关文章
- P6604 [HNOI2016]序列 加强版
*I. P6604 [HNOI2016]序列 加强版 摘自学习笔记 简单树论 笛卡尔树部分例题 I. 和 P6503 比较类似.我们设 \(f_i\) 表示全局以 \(i\) 结尾的子区间的最小值之和 ...
- [BZOJ4540][HNOI2016]序列 莫队
4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ...
- [Bzoj4540][Hnoi2016] 序列(莫队 + ST表 + 单调队列)
4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1567 Solved: 718[Submit][Status] ...
- [HNOI2016]序列 CDQ+DP
[HNOI2016]序列 CDQ 链接 loj 思路 一个点最小变为l,最大变为r,不变的时候为v 那么j能在i前面就要满足. \(j<i\) \(r[j]<=v[i]\) \(v[j]& ...
- BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]
4540: [Hnoi2016]序列 题意:询问区间所有子串的最小值的和 不强制在线当然上莫队啦 但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做 想到单调栈求一下,但是对 ...
- 【LG3246】[HNOI2016]序列
[LG3246][HNOI2016]序列 题面 洛谷 题解 60pts 对于每个位置\(i\),单调栈维护它往左第一个小于等于它的位置\(lp_i\)以及往右第一个小于它的位置\(rp_i\). 那么 ...
- 4540: [Hnoi2016]序列
4540: [Hnoi2016]序列 https://www.lydsy.com/JudgeOnline/problem.php?id=4540 分析: 莫队+RMQ+单调栈. 考虑加入一个点后,区间 ...
- BZOJ4540 Hnoi2016 序列 【莫队+RMQ+单调栈预处理】*
BZOJ4540 Hnoi2016 序列 Description 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- ...
- 【BZOJ4540】[Hnoi2016]序列 莫队算法+单调栈
[BZOJ4540][Hnoi2016]序列 Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,a ...
随机推荐
- 转MySQL详解--索引
写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储100条记录.如果没有索引,查询将 ...
- Linux 下 PHP 扩展 PDO 编译安装
1.进入 PHP 的软件包 pdo 扩展目录中(注:不是 PHP 安装目录) [root@tester /]# /home/tdweb/php-5.4.34/ext/pdo_mysql 执行 phpi ...
- valgrind检查still reachable情况
valgrind --leak-check=yes检查bufr编解码程序运行时提示still reachable: 568 bytes in 1 blocks,如下图示: 于是怀疑有内存泄漏,难道是m ...
- Vue学习(五):列表渲染
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- python3.x 编码问题
- cocos2d-x 粒子系统
粒子系统是模拟自然界中的一些粒子的物理运动的效果,如烟雾,下雪,下雨,火,爆炸等. 粒子发射模式 粒子系统的发射模式的时候有两种方式:重力模式和半径模式. 粒子系统属性 属性名 行为 模式 d ...
- 软件工程项目组Z.XML会议记录 2013/09/25
软件工程项目组Z.XML会议记录 [例会时间]2013年9月25日周三21:30-22:10 [例会形式]小组讨论 [例会地点]三号公寓楼会客厅 [例会主持]李孟 [会议记录]肖俊鹏 会议整体流程 签 ...
- SSH答疑解惑系列(三)——Struts2的异常处理
Struts2的异常采用声明式异常捕捉,具体通过拦截器来实现. 在项目中,我们可以在Action中直接抛出异常,剩下的就交给Struts2的拦截器来处理了.当然,我们需要进行相关配置. Struts2 ...
- 正则awk和查看文件行数
[root@WebServer aa]# cat oldboy.txt I am oldboy myqq is 49000448[root@WebServer aa]# cat oldboy.txt ...
- LevelDB速记
LevelDb的基本结构如下: 由六大部分组成: 一.MemTable,用户写入和读取的直接对象, 二.Immutable MemTable,用户状态写入的对象写满的MemTable之后会转为Immu ...