给出一个长度为 \(n\) 的序列 \(a_1,a_2,\cdots,a_n\) ,求一子段 \(a_l, a_{l + 1}, a_{l + 2}, \cdots, a_{r - 1}, a_r\) ,满足 \(\max\{a_l,\cdots,a_r\} - \min\{a_l,\cdots,a_r\} \geq r - l + 1\)。若有多个,输出任意一个子段的左右端点即可。若不存在,输出
NO
。
\(n \leq 2 \times 10 ^ 5\)
虽然做出来了,但做复杂了。所以又没有完全做出来(
当时想的是直接把 \(\max - \min\) 的条件改成 \(a_r - a_l\) ,然后再找。因为最优的情况必然是一端为 \(\min\) 另一端为 \(\max\) 。然后忘记考虑 \(a_l - a_r\) 的情况还 WA
了一发。
后来讲题的时候,说先考虑相邻两个是否有合适的,如果有就有了。如果没有,说明相邻两个的差值不超过 \(1\) ,那么随着子段的延伸,\(\max - \min\) 永远追不上子段长度,就肯定是 NO
了。
很妙,可惜我错过了,很多事情,错过一次,就没有第二次了。
先从局部着手,考虑动态的变化。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int main() {
int T = 0;
scanf("%d", &T);
for (int G = 1; G <= T; G++) {
int n = 0, lst = -1;
int l = -1, r = -1;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int a = 0;
scanf("%d", &a);
if (i >= 2 && abs(lst - a) >= 2) {
l = i - 1, r = i;
}
lst = a;
}
if (l == -1) printf("NO\n");
else printf("YES\n%d %d\n", l, r);
}
return 0;
}
标签:min,int,Interesting,NO,cdots,max,CF1270B,Subarray,include
From: https://www.cnblogs.com/kirakiraa/p/18097039