CSU 1553 Good subsequence(暴力求解)

题意

求一个子序列满足 最大值 - 最小值 <= k的最大长度。

解析

假设之前最大的是a[4],最小的是a[5]
连续子串已经是 a[0] ~ a[10]
这时候判断a[11]是否符合,
两种情况
一种a[11]比a[4]大
这时候判断他 a[11] - min <= k 是否符合
假如不符合
就向前查找,第一个a[j] >= (a[11] - k)的数字
这时候子串长度 = 11 - j 的位置
变成了min = a[j], max = a[11]
不要被数据范围给吓到了,n虽然有10万,但是最小值和最大是满足单调递增的,所以不会算很慢。

AC代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
int a[N], n, k;

int main() {
    while(scanf("%d%d", &n, &k) != EOF) {
        for(int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
        }
        int maxa, mina;
        maxa = mina = a[0];
        int ans, len;
        ans = len = 1;
        for(int i = 1; i < n; i++) {
            if(a[i] > maxa) {
                maxa = a[i];
                if(a[i] - mina <= k) {
                    len++;
                }else {
                    int j;
                    mina = INF;
                    for(j = i; j >= 0; j--) {
                        if(abs(a[i] - a[j]) > k) break;
                        mina = min(mina, a[j]);
                    }
                    len = i - j;
                }
            }else if(a[i] < mina) {
                mina = a[i];
                if(maxa - a[i] <= k) {
                    len++;
                }else {
                    int j;
                    maxa = -INF;
                    for(j = i; j >= 0; j--) {
                        if(abs(a[j] - a[i]) > k) break;
                        maxa = max(maxa, a[j]);
                    }
                    len = i - j;
                }
            }else {
                len++;
            }
            ans = max(ans, len);
        }
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(CSU,1553)