【HNOI 2016】序列
Problem
Description
给定长度为 \(n\) 的序列:\(a_1, a_2, \cdots , a_n\),记为 \(a[1 \colon n]\)。类似地,\(a[l \colon r]\)(\(1 \leq l \leq r \leq N\))是指序列:\(a_{l}, a_{l+1}, \cdots ,a_{r-1}, a_r\)。若 \(1\leq l \leq s \leq t \leq r \leq n\),则称 \(a[s \colon t]\)是 \(a[l \colon r]\) 的子序列。
现在有 \(q\) 个询问,每个询问给定两个数 \(l\) 和 \(r\),\(1 \leq l \leq r \leq n\),求 \(a[l \colon r]\) 的不同子序列的最小值之和。例如,给定序列
\(5, 2, 4, 1, 3\),询问给定的两个数为 \(1\) 和 \(3\),那么 \(a[1 \colon 3]\) 有 \(6\) 个子序列 \(a[1 \colon 1], a[2 \colon 2], a[3 \colon 3], a[1 \colon 2],a[2 \colon 3], a[1 \colon 3]\),这 \(6\) 个子序列的最小值之和为 \(5+2+4+2+2+2=17\)。
Input Format
输入文件的第一行包含两个整数 \(n\) 和 \(q\),分别代表序列长度和询问数。
接下来一行,包含 \(n\) 个整数,以空格隔开,第 \(i\) 个整数为 \(a_i\),即序列第 \(i\) 个元素的值。
接下来 \(q\) 行,每行包含两个整数 \(l\) 和 \(r\),代表一次询问。
Output Format
对于每次询问,输出一行,代表询问的答案。
Sample
Input
5 5
5 2 4 1 3
1 5
1 3
2 4
3 5
2 5
Output
28
17
11
11
17
Range
对于 \(100\%\) 的数据,\(1 \leq n,q \leq 100000 ,|a_i| \leq 10^9\)
Algorithm
莫队
Mentality
第一眼觉得做法和 \(HNOI2017\) 的影魔应该是一样的,然后发现由于这一题的区间最小值可能存在多个,那么影魔里的就完全不适用了 \(QwQ\) 。
那看着这个数据范围,我们能想到三种复杂度:\(nlog\) 、\(nlog^2\)、\(n\sqrt{n}\) 。
然后发现可以离线,询问是区间形式的,我们便不由得想到莫队了。
接下来考虑莫队里的计算步骤:从 \([l,r]\) -> \([l,r+1]\) 的增量,由于其他三个计算本质相同,不多做讨论。
首先,我们设 \(p\) 为区间 \([l,r+1]\) 的最小值所在位置,那么对于区间左端点在 \(l\sim p\) ,右端点在 \(r+1\) 的区间,它们的最小值肯定都是 \(a[p]\) 。则这一坨区间对答案的贡献为 \(a[p]*(p-l+1)\) 。
那剩下的左端点在 \(p+1\sim r\) 的区间的贡献呢?
其实我们可以稍加思考,就会发现我们应该考虑先处理出两个 \(ll[i],rr[i]\) 数组,分别是 \(i\) 左边第一个比 \(i\) 小的位置,\(i\) 右边第一个比 \(i\) 小的位置。
那么我们设 \(f_l[r+1]\) 右端点在 \(r+1\) ,而左端点在 \([1,r+1]\) 范围的区间的最小值之和:
\[ f_l[r+1]=(r+1-ll[r+1])*a[r]+(ll[r+1]-ll[ll[r+1]])*a[ll[r+1]]+\dots + 0 \]
也即按照区间最小值分段,只要右端点固定,那么区间的最小值肯定是连续相同的,我们一个个区间去计算就好了。
然后我们观察到反正这个式子是从 \(ll[r+1]\) 把值转移上来的,那我们自然可以写出如下 \(DP\) 式:
\[ f_l[r+1]=(r+1-ll[r+1])*a[r]+f_l[ll[r+1]] \]
不难发现,对于原式子中,我们沿着一段段连续的区间最小值计算答案,而对于其中任意一个 "\(ll[i]\)" ,我们只需要把后面那截砍掉,也即 \(f_l[r+1]-f_l[ll[i]]\) ,这显然就是右端点在 \(r+1\) ,左端点在 \([ll[i]+1,r+1]\) 这段范围内的区间最小值之和。
由于 \(p\) 已经是区间内最小的位置了,所以对于 \(p+1\sim r\) 这些点,它们的 \(ll[i]\) 的值要么就是 \(a[p]\) ,要么就不小于 \(a[p]\)。所以 \(p\) 一定是计算 \(r+1\) 的答案中的某个 "\(ll[i]\)" ,那我们只需要用 \(f_l[r+1]\) 减去 \(f_l[p]\) 即可得到左端点在 \(p+1\sim r\) 的区间的答案。
总结一下,\([l,r]\) -> \([l,r+1]\) 的增量为:
\[ a[p]*(p-l+1)+f_l[r+1]-f_l[p] \]
对于 \([l,r]\) -> \([l-1,r]\) 也同理,我们只需要处理出一个类似的 \(f_r\) 数组即可。
Code
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
int n, size, Q, a[100001];
int minn[100001][18], pos[100001][18], Log[100001];
int top, ll[100001], rr[100001], stack[100001];
int L, R;
long long ans, Ans[100001], fr[100001], fl[100001];
struct node {int l, r, d;
} k[100001];
bool cmp(node a, node b) {return (a.l / size) == (b.l / size) ? a.r < b.r : (a.l / size) < (b.l / size);
}
int find(int l, int r) {if (l > r) return 0;if (l == r) return pos[l][0];int x = Log[r - l], p;return minn[l][x] > minn[r - (1 << x) + 1][x] ? pos[r - (1 << x) + 1][x]: pos[l][x];} //寻找最小值位置
void init() {cin >> n >> Q;size = sqrt(n);int now = 2;for (int i = 2; i <= (int)1e5; i++) {Log[i] = Log[i - 1];if (i == now) Log[i]++, now <<= 1;} //预处理对数for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);minn[i][0] = a[i], pos[i][0] = i;}for (int i = 1; i <= Q; i++) scanf("%d%d", &k[i].l, &k[i].r), k[i].d = i;sort(k + 1, k + Q + 1, cmp); //离线询问for (int j = 1; j <= 17; j++)for (int i = 1; i <= n - (1 << j) + 1; i++) {pos[i][j] = pos[i][j - 1],minn[i][j] = min(minn[i][j - 1], minn[i + (1 << (j - 1))][j - 1]);if (minn[i][j] != minn[i][j - 1])pos[i][j] = pos[i + (1 << (j - 1))][j - 1];} //预处理 rmqstack[top = 0] = 0;for (int i = 1; i <= n; i++) {while (top && a[stack[top]] >= a[i]) top--;ll[i] = stack[top], stack[++top] = i;}for (int i = 1; i <= n; i++) fl[i] = fl[ll[i]] + 1ll * (i - ll[i]) * a[i];stack[top = 0] = n + 1;for (int i = n; i >= 1; i--) {while (top && a[stack[top]] >= a[i]) top--;rr[i] = stack[top], stack[++top] = i;} //单调栈处理 ll,rr 数组for (int i = n; i >= 1; i--)fr[i] = fr[rr[i]] + 1ll * (rr[i] - i) * a[i]; //计算 fl,fr 数组
}
long long workr(int x) {int p = find(L, x);return 1ll * a[p] * (p - L + 1) + fl[x] - fl[p];
}
long long workl(int x) {int p = find(x, R);return 1ll * a[p] * (R - p + 1) + fr[x] - fr[p];
}
void solve() {L = k[1].l, R = k[1].l - 1;for (int i = 1; i <= Q; i++) {while (R < k[i].r) ans += workr(++R);while (L > k[i].l) ans += workl(--L);while (R > k[i].r) ans -= workr(R--);while (L < k[i].l) ans -= workl(L++);Ans[k[i].d] = ans;}
}
int main() {init(); //预处理和读入solve();for (int i = 1; i <= Q; i++) printf("%lld\n", Ans[i]);
}
转载于:https://www.cnblogs.com/luoshuitianyi/p/10632175.html
【HNOI 2016】序列相关推荐
- 【HNOI 2016】大数
Problem Description 小 B 有一个很大的数 \(S\),长度达到了 \(N\) 位:这个数可以看成是一个串,它可能有前导 \(0\),例如 00009312345 .小 B 还有一 ...
- HNOI 2016 暴力之旅
Day1 T1 看到这题,我瞬间想到用暴力做. 小小思考了一下,我便打起了暴力. 是这样的: 题目每次给出了俩点,和一个限制ta和tb,于是乎,我便从一个点开始,往周围延伸.延伸的标准是酱紫的,一条线 ...
- cs213n课程笔记
文章目录 一.计算神经网络(P1) 1 激活函数 实际操作: 2 数据预处理 3 权重初始化 4 批标准化 二.训练神经网络(P2) 1.梯度下降 实际使用 2.避免过拟合 3.正则化 Trainin ...
- 基础省选+NOI-第1部分 数据结构进阶(I)
1.莫队 HRBU ACM 莫队 线段树 树状数组_哔哩哔哩_bilibili 莫队+ST表综合题 洛谷p3246[HNOI]序列_哔哩哔哩_bilibili 0325[莫队2]_哔哩哔哩_bilib ...
- python天天向上3.2-Python入门习题3.天天向上
例3.1 一年365天,以第一天的能力值为基数,记为1.0,当好好学习时能力值相比前一天提高1%,当没有学习时能力值相比前一天下降1%.每天努力(dayup)和每天放任(daydown),一年下来的能 ...
- Cogs 2382. [HZOI 2016]最佳序列
Cogs 2382. [HZOI 2016]最佳序列 ★☆ 输入文件:bestseq.in 输出文件:bestseq.out 简单对比 时间限制:1 s 内存限制:128 MB [题目 ...
- 2016百度实习编程题:括号序列
不知如何解决 1.感觉贪心或者动态规划,不知道如何解决 2.做过生成合法括号序列的题目,想到用DFS补成合法的括号,然而没有成功
- bzoj1562[NOI2009]变换序列——2016——3——12
任意门:http://www.lydsy.com/JudgeOnline/problem.php?id=1562 题目: 对于0,1,-,N-1的N个整数,给定一个距离序列D0,D1,-,DN-1,定 ...
- Python计算序列中数字最大差值(美团2016校招笔试题)
题目要求:给定一个包含若干数字的序列A(本文以列表为例),求满足0≤a≤b<n(其中n为序列长度)的A[b] - A[a]的最大值. 编程要点:循环结构用法,切片,内置函数enumerate() ...
最新文章
- ModelSim 使用笔记1
- 判断元素(expected_conditions)
- u-boot移植随笔:System.map文件格式
- CentOS Linux解决Device eth0 does not seem to be present【转】
- tbytes 转 十六进制 string
- asp.net删除cookie
- scrapy持久化存储
- Linux事件驱动网络编程,Linux系统编程之事件驱动
- 【java web学习小结】JSP的response对象的动态响应实例
- java jsp聊天系统_jsp 在线客服聊天源码(websocket)
- My Neighbor Alice新一轮土地销售分析
- 华为服务器克隆linux,华为RH2288H V3服务器磁盘阵列配置RAID
- 【DC系列】DC-4靶机渗透练习
- 微信小程序利用百度api达成植物识别
- RGB颜色转HEX进制与单位换算
- CE 传导发射试验台布置
- 机器学习、深度学习、强化学习
- 【交互设计】如何设计“取消”按钮
- C++常用STL库详细总结
- 二总线技术为什么下行采用电压信号,上行采用电流信号?是什么传输的