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 xy 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 1n,q200000) — 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 1ai109) — 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 1lrn) — 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 xyz. 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 433. 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;
}
### Codeforces Round 927 Div. 3 比赛详情 Codeforces是一个面向全球程序员的比赛平台,定期举办不同级别的编程竞赛。Div. 3系列比赛专为评级较低的选手设计,旨在提供更简单的问题让新手能够参与并提升技能[^1]。 #### 参赛规则概述 这类赛事通常允许单人参加,在规定时间内解决尽可能多的问题来获得分数。评分机制基于解决问题的速度以及提交答案的成功率。比赛中可能会有预测试案例用于即时反馈,而最终得分取决于系统测试的结果。此外,还存在反作弊措施以确保公平竞争环境。 ### 题目解析:Moving Platforms (G) 在这道题中,给定一系列移动平台的位置和速度向量,询问某时刻这些平台是否会形成一条连续路径使得可以从最左端到达最右端。此问题涉及到几何学中的线段交集判断和平面直角坐标系内的相对运动分析。 为了处理这个问题,可以采用如下方法: - **输入数据结构化**:读取所有平台的数据,并将其存储在一个合适的数据结构里以便后续操作。 - **时间轴离散化**:考虑到浮点数精度误差可能导致计算错误,应该把整个过程划分成若干个小的时间间隔来进行模拟仿真。 - **碰撞检测算法实现**:编写函数用来判定任意两个矩形之间是否存在重叠区域;当发现新的连接关系时更新可达性矩阵。 - **连通分量查找技术应用**:利用图论知识快速求解当前状态下哪些节点属于同一个集合内——即能否通过其他成员间接相连。 最后输出结果前记得考虑边界条件! ```cpp // 假设已经定义好了必要的类和辅助功能... bool canReachEnd(vector<Platform>& platforms, double endTime){ // 初始化工作... for(double currentTime = startTime; currentTime <= endTime ;currentTime += deltaT){ updatePositions(platforms, currentTime); buildAdjacencyMatrix(platforms); if(isConnected(startNode,endNode)){ return true; } } return false; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值