ABC 247 | E - Max Min
题目描述
给定一个长度为\(N\)的序列\(A = (A_1, A_2, A_3, ...,A_N)\)和两个数\(X, Y\),求满足以下条件的\((L, R)\)的个数。
- \(1 \le L \le R \le N\)
- \(A_L, A_{L + 1}, ...,A_{R}\)的最大值为\(X\),最小值为\(Y\)
数据范围
- \(1 \le N \le 2 \times 10^5\)
- \(1 \le A_i \le 2 \times 10^5\)
- \(1 \le Y \le X \le 2 \times 10^5\)
解题思路
该题为计数题,可以在\(O(N^3)\)的时间复杂度内被暴力解决,由于数据范围为\(2 \times 10^5\),考虑对算法进行优化。
观察到题目的给出的条件发现:符合条件的序列中不会包含大于\(X\)和小于\(Y\)的数,故考虑以这些数为分界线划分数组,然后对其中的每一个子段求符合条件的序列个数。
这些子段中的\(A_i\)满足\(Y \le A_i \le X\),故寻找最大值为\(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;
}

浙公网安备 33010602011771号