ABC 247 | E - Max Min

题目描述

给定一个长度为N的序列A=(A1,A2,A3,...,AN)和两个数X,Y,求满足以下条件的(L,R)的个数。

  • 1LRN
  • AL,AL+1,...,AR的最大值为X,最小值为Y

数据范围

  • 1N2×105
  • 1Ai2×105
  • 1YX2×105

解题思路

该题为计数题,可以在O(N3)的时间复杂度内被暴力解决,由于数据范围为2×105,考虑对算法进行优化。
观察到题目的给出的条件发现:符合条件的序列中不会包含大于X和小于Y的数,故考虑以这些数为分界线划分数组,然后对其中的每一个子段求符合条件的序列个数。
这些子段中的Ai满足YAiX,故寻找最大值为X且最小值为Y的序列等价于寻找包含X且包含Y的序列,符合条件的序列可以通过双指针算法在O(L)复杂度内求得,L为该段序列长度。故对于整个数组长度为N的序列,时间复杂度为O(N)

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

int n, x, y;
int a[N];

ll calc(int st, int ed){
    ll ans = 0, cntx = 0, cnty = 0;
    for(int l = st, r = st; l < ed; l ++){
        while(!(cntx && cnty) && r < ed){
            if(a[r] == x) cntx ++;
            if(a[r] == y) cnty ++;
            r ++;
        }
        if(cntx && cnty) ans += (ed - r + 1);
        if(a[l] == x) cntx --;
        if(a[l] == y) cnty --;
    }
    return ans;
}

int main()
{
    scanf("%d%d%d", &n, &x, &y);
    for(int i = 0; i < n; i ++) scanf("%d", &a[i]);

    ll ans = 0;
    for(int i = 0; i < n; ){
        int l = i;
        while(i < n && a[i] <= x && a[i] >= y) i ++;
        if(i > l) ans += calc(l, i);
        i ++;
    }
    printf("%lld\n", ans);
    return 0;
}

posted @   小菜珠的成长之路  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示