P6604 [HNOI2016]序列 加强版
*I. P6604 [HNOI2016]序列 加强版
摘自学习笔记 简单树论 笛卡尔树部分例题 I.
和 P6503 比较类似。我们设 \(f_i\) 表示全局以 \(i\) 结尾的子区间的最小值之和,令 \(p_i\) 为下标在 \(i\) 之前第一个比 \(a_i\) 小的位置,显然有 \(f_i=f_{p_i}+(i-p_i)a_i\):因为 \(a_i\) 对 \(p_i\) 以及 \(p_i\) 以前的最小值没有影响(即 \([1,p_i]\) 与 \([1,i]\),\([2,p_i]\) 与 \([2,i]\cdots\) \([p_i,p_i]\) 与 \([p_i,i]\) 的最小值相同),所以可以直接由 \(f_{p_i}\) 转移得来。而根据 \(p_i\) 的定义,后面 \(i-p_i\) 个子序列(即 \([p_i+1,i],[p_i+2,i]\cdots,[i,i]\))的最小值为 \(a_i\)。
注意到 \(p_i\) 实际相当于 \(i\) 在笛卡尔树上第一个向左走的父亲,求 \(p_i\) 的过程十分类似构建笛卡尔树:笛卡尔树上每个节点的祖先由左右两个单调栈构成。
考虑对一个区间求答案:求出区间最小值的位置 \(p\),那么左端在 \(p\) 左边,右端在 \(p\) 右边的子区间最小值为 \(a_p\),故答案加上 \(a_p\times (p-l+1)\times (r-p+1)\)。此外,我们还需求出 \([l,p)\) 与 \((p,r]\) 的答案:考虑 \((p,r]\) 每个位置对答案的贡献都是 \(f_r-f_p\),因为 \([i,p]\) 与 \([i,r]\ (1\leq i\leq p)\) 的最小值相同。前缀和优化可以做到 \(\mathcal{O}(1)\) 回答每个询问。对于 \([l,p)\) 同理,我们只需预处理出 \(g_i\) 表示全局以 \(i\) 开头的子区间的最小值之和并类似处理即可。
复杂度瓶颈在于区间 RMQ,时间复杂度 \(\mathcal{O}(n\log n+q)\)。
const int N = 1e5 + 5;
const int K = 17;
namespace gen {
ull s, a, b, c, las = 0;
ull rand() {return s ^= (a + b * las) % c;}
}
int n, q, type, stc[N], *top = stc, a[N], lg[N], pre[N], suf[N];
ll mi[K][N], fp[N], gp[N], fs[N], gs[N]; ull res;
int cmp(int x, int y) {return a[x] < a[y] ? x : y;}
int RMQ(int l, int r) {int d = lg[r - l + 1]; return cmp(mi[d][l], mi[d][r - (1 << d) + 1]);}
int main(){
cin >> n >> q >> type;
for(int i = 1; i <= n; i++) a[i] = read(), mi[0][i] = i;
for(int i = 2; i <= n; i++) lg[i] = lg[i >> 1] + 1;
for(int i = 1; i <= lg[n]; i++)
for(int j = 1; j + (1 << i) - 1 <= n; j++)
mi[i][j] = cmp(mi[i - 1][j], mi[i - 1][j + (1 << i - 1)]);
for(int i = 1; i <= n; i++) {
while(*top && a[*top] >= a[i]) suf[*top--] = i; // 可以类比求笛卡尔树的过程: ls[i] = *top, 因此 suf[*top] = i;
pre[i] = *top, *++top = i; // 同理, rs[*top] = i, 所以 pre[i] = *top: 笛卡尔树上每个节点的祖先是由两个单调栈构成的!
}
for(int i = 1; i <= n; i++)
fp[i] = fp[pre[i]] + 1ll * a[i] * (i - pre[i]), gp[i] = gp[i - 1] + fp[i];
for(int i = n; i; i--)
fs[i] = fs[suf[i]] + 1ll * a[i] * (suf[i] - i), gs[i] = gs[i + 1] + fs[i];
if(type) gen :: s = read(), gen :: a = read(), gen :: b = read(), gen :: c = read();
for(int i = 1, l, r; i <= q; i++) {
if(type == 0) l = read(), r = read();
else {
l = gen :: rand() % n + 1;
r = gen :: rand() % n + 1;
if(l > r) swap(l, r);
}
ll p = RMQ(l, r), ans;
ans = a[p] * (r - p + 1) * (p - l + 1);
ans += gp[r] - gp[p] - fp[p] * (r - p);
ans += gs[l] - gs[p] - fs[p] * (p - l);
res ^= gen :: las = ans;
}
cout << res << endl;
return flush(), 0;
}
P6604 [HNOI2016]序列 加强版的更多相关文章
- LOJ 6057 - [HNOI2016]序列 加强版再加强版
Description 给定一个长度为 \(n\le 3*10^6\) 的序列 \(q\le 10^7\) 次询问每次求区间 \([l,r]\) 的所有子区间的最小值的和 询问随机 Solution ...
- 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]序列 莫队
4540: [Hnoi2016]序列 Time Limit: 20 Sec Memory Limit: 512 MB Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n ...
- 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 ...
- [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]& ...
随机推荐
- 安卓开发——WebView+Recyclerview文章详情页,解决高度问题
安卓开发--WebView+Recyclerview文章详情页,解决高度问题 最近在写一个APP时,需要显示文章详情页,准备使用WebView和RecyclerView实现上面文章,下面评论.出现了W ...
- Go语言核心36讲(Go语言进阶技术七)--学习笔记
13 | 结构体及其方法的使用法门 我们都知道,结构体类型表示的是实实在在的数据结构.一个结构体类型可以包含若干个字段,每个字段通常都需要有确切的名字和类型. 前导内容:结构体类型基础知识 当然了,结 ...
- STM32采集AD的输入阻抗问题
在做一款消费电子产品时,需要采集电池电压(3.3V-4.2V),同时在休眠的时候希望尽量减小待机电流.电池电压采集电路采用两个1%的300K电阻进行分压,由该电路引起的待机电路为4.2/(300+30 ...
- Python环境配置详细步骤以及第一个程序
打开python官网:https://www.python.org/ 在官网找与自己电脑系统匹配的版本路径 这里以python3.7.2版本为例: 下载完成后,使用管理员身份进行安装: 打开命令提 ...
- Linux C 数据结构 ->单向链表
之前看到一篇单向链表的博文,代码也看着很舒服,于是乎记录下来,留给自己~,循序渐进,慢慢 延伸到真正的内核链表~(敢问路在何方?路在脚下~) 1. 简介 链表是Linux 内核中最简单,最普通的数据结 ...
- p->next = q, p = q->next, q->next = p->next的区别
- Centos7下安装BlockScout
简介 BlockScout是一个Elixir应用程序,允许用户搜索以太坊网络(包括所有叉子和侧链)上的交易,查看账户和余额以及验证智能合约.BlockScout为用户提供了一个全面,易于使用的界面,以 ...
- Java多线程之Atomic:原子变量与原子类
Atomic简介 Atomic包是java.util.concurrent下的另一个专门为线程安全设计的Java包,包含多个原子操作类这个包里面提供了一组原子变量类. 其基本的特性就是在多线程 ...
- 【数据结构&算法】11-树基础&二叉树遍历
目录 前言 树的定义 树的存储结构 双亲表示法 孩子表示法 孩子兄弟表示法 二叉树 定义 特点 形态 特殊二叉树 斜树 满二叉树 完全二叉树 二叉树的性质 二叉树的存储结构 二叉树的顺序存储结构 二叉 ...
- redis学习笔记(详细)——高级篇
redis学习笔记(详细)--初级篇 redis学习笔记(详细)--高级篇 redis配置文件介绍 linux环境下配置大于编程 redis 的配置文件位于 Redis 安装目录下,文件名为 redi ...