Codeforces Round 869 Div.1 A. Almost Increasing Subsequence 题解
Almost Increasing Subsequence
题面描述
给定长度为 n n n 的一个序列 a a a 以及 q q q 次询问,每次询问给出 l l l 和 r r r,找出序列 a a a 在 [ l , r ] [l,r] [l,r] 内最长的几乎递增子序列,并输出其长度。
几乎递增的定义:如果一个序列中不存在连续的三个数 x x x, y y y, z z z,使得 x ≥ y ≥ z x \ge y \ge \ z x≥y≥ z,则这个序列是几乎递增的。
输入格式
The first line of input contains two integers, n n n and q q q ( 1 ≤ n , q ≤ 200 000 1 \leq n, q \leq 200\,000 1≤n,q≤200000) — the length of the array a a a and the number of queries.
The second line contains n n n integers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an ( 1 ≤ a i ≤ 1 0 9 1 \leq a_i \leq 10^9 1≤ai≤109) — the values of the array a a a.
Each of the next q q q lines contains the description of a query. Each line contains two integers l l l and r r r ( 1 ≤ l ≤ r ≤ n 1 \leq l \leq r \leq n 1≤l≤r≤n) — the query is about the subarray a l , a l + 1 , … , a r a_l, a_{l+1}, \dots, a_r al,al+1,…,ar.
输出格式
For each of the q q q queries, print a line containing the length of the longest almost-increasing subsequence of the subarray a l , a l + 1 , … , a r a_l, a_{l+1}, \dots, a_r al,al+1,…,ar.
样例 #1
样例输入 #1
9 8
1 2 4 3 3 5 6 2 1
1 3
1 4
2 5
6 6
3 7
7 8
1 8
8 8
样例输出 #1
3
4
3
1
4
2
7
1
提示
In the first query, the subarray is a 1 , a 2 , a 3 = [ 1 , 2 , 4 ] a_1, a_2, a_3 = [1,2,4] a1,a2,a3=[1,2,4]. The whole subarray is almost-increasing, so the answer is 3 3 3.
In the second query, the subarray is a 1 , a 2 , a 3 , a 4 = [ 1 , 2 , 4 , 3 ] a_1, a_2, a_3,a_4 = [1,2,4,3] a1,a2,a3,a4=[1,2,4,3]. The whole subarray is a almost-increasing, because there are no three consecutive elements such that x ≥ y ≥ z x \geq y \geq z x≥y≥z. So the answer is 4 4 4.
In the third query, the subarray is a 2 , a 3 , a 4 , a 5 = [ 2 , 4 , 3 , 3 ] a_2, a_3, a_4, a_5 = [2, 4, 3, 3] a2,a3,a4,a5=[2,4,3,3]. The whole subarray is not almost-increasing, because the last three elements satisfy 4 ≥ 3 ≥ 3 4 \geq 3 \geq 3 4≥3≥3. An almost-increasing subsequence of length 3 3 3 can be found (for example taking a 2 , a 3 , a 5 = [ 2 , 4 , 3 ] a_2,a_3,a_5 = [2,4,3] a2,a3,a5=[2,4,3] ). So the answer is 3 3 3.
链接
思路
- 根据题意,几乎递增的序列不包含三个连续元素构成非递增序列。
- 那么问题可以转化为找出给定数组中所有的非递增子数组,其中非递增子数组的长度>2的是不满足条件的。
- 因此当非递增子数组长度大于2时,只取其首元素和尾元素,去掉内部元素。
- 那么我们可以维护1到i区间内的不满足条件的内部元素个数d[i]。
- 当查询区间答案时,只需用d[r]减去d[l+1]就是该区间内不满足条件的内部元素个数。
- 那么一个区间的答案即为区间长度len-(d[r]-d[l+1])。
- 至于为什么是d[r]-d[l+1]而不是d[r]-d[l-1],下面给出解释:
- 因为不满足条件的内部元素被统计在内的前提条件是至少包含三个元素。
- 而区间l到r中,位置l和l+1的元素前面只有零个/一个元素,加起来达不到三个元素。
- 即预处理时在位置l和位置l+1统计的数量在该l,r区间中实际不应当计算在内。
- 因此减去的应当是d[l+1]而非d[l-1]。
- 另外需要注意的是:
- l与r相等时,不存在l+1位置,则len-(d[r]-d[l+1])公式不适用,应改为len-(d[r]-d[l])。
我一开始就是因为没特判WA了一发。
代码
#include <bits/stdc++.h>
using namespace std;
#define max_Heap(x) priority_queue<x, vector<x>, less<x>>
#define min_Heap(x) priority_queue<x, vector<x>, greater<x>>
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<long long, long long> PLL;
const double PI = acos(-1);
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, q;
cin >> n >> q;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
vector<int> d(n + 1, 0);
// 预处理1到i区间内的不满足条件的内部元素个数d[i]
for (int i = 3; i <= n; i++)
{
if (a[i - 2] >= a[i - 1] && a[i - 1] >= a[i]) // 存在不满足条件的内部元素时
{
d[i] = d[i - 1] + 1;
}
else // 继承
{
d[i] = d[i - 1];
}
}
int l, r, len;
while (q--)
{
cin >> l >> r;
len = r - l + 1;
if (len == 1) // 需特判len==1,因为l和r相等时l+1>r,因此不符合
cout << len - (d[r] - d[l]) << '\n';
// 当然,此时d[r]-d[l]等于0,因此写成cout << 1 << '\n'也是OK的
else
cout << len - (d[r] - d[l + 1]) << '\n';
}
return 0;
}
原文地址:https://blog.csdn.net/bbc_plus/article/details/137786919
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!