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 root密码的方法
方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...
- 在Ubuntu Server 16.04 LTS下安装VMware Tools
1.开启ubuntu server虚拟机 2.vmware workstation菜单项,选取虚拟机(M) --> 安装VMware Tools 3.mkdir /mnt/cdrom #创建一 ...
- 解析车辆VIN码识别(车架号识别)系统
很多人在购买车辆的时候,只关注性能.外观.内饰等,其实真正的内行是首先看车辆的VIN码,也叫车架号码. VIN码(车架号码)是一辆车的唯一身份证明,一般在车辆的挡风玻璃处,有的在车辆防火墙上,或B柱铭 ...
- Qt Creater 制作汽车仪表盘
最近项目用到了模拟仪表,网上下载大神编写的按个仪表Meter没有成功 转战 QWt 编译后,在creater中仍然无法使用,只可以在代码中使用 百度说是我编译的版本不对 扔到 开始做自己的 这个用到了 ...
- deepin linux 安装/启动jeakins报错:处理
ERROR: No Java executable found in current PATH: /bin:/usr/bin:/sbin:/usr/sbin 安装报错: 1.如还未安装java,则安装 ...
- 基于Python的接口自动化-01
为什么要做接口测试 当前互联网产品迭代速度越来越快,由之前的2-3个月到个把月,再到班车制,甚至更短,每次发版之前都需要对所有功能进行回归测试,在人力资源有限的情况下,做自动化测试很有必要.由于UI更 ...
- 总结java操作MySQL 即JDBC的使用
java.sql包中存在DriverManager类,Connection接口,Statement接口和ResultSet接口.类和接口作用如下: DriverManager:主要用于管理驱动程序和连 ...
- C++STL——map
一.相关定义 map 关联容器,存储相结合形成的一个关键值和映射值的元素 提供一对一(第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可以称为该关键字的值)的数据处理能力 map对象是模 ...
- PhpStorm 配置IDE
IDE => Xdebug => Apache(XAMPP) => Firefox + easist Xdebug 1>XAMPP停止apache服务;2>在安装目录下找 ...
- 【iOS开发】创建单例的两种方法
创建一个单例很多办法.我先列举一个苹果官方文档中的写法. [cpp] view plaincopy static AccountManager *DefaultManager = nil; + ( ...