GYM 102082 B Arithmetic Progressions【DP】

https://codeforces.com/gym/102082

题意:给你一个序列,从中选若干个元素,使这些元素可以组成一个等差序列,求这个等差序列长度的最大值。

分析:对于每个a[i]可以枚举以它为结尾的不同公差的序列,因为a[i]的范围很大,所以直接用等差数列的倒数第二项下标j来表示公差,那么dp[i][j]表示以i为结尾,j为倒数第二项,公差是a[i]-a[j]的最长序列。然后二分找倒数第三项转移状态即可。

#include "bits/stdc++.h"

namespace fastIO {
#define BUF_SIZE 100000
    bool IOerror = 0;

    inline char nc() {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if (p1 == pend) {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if (pend == p1) {
                IOerror = 1;
                return -1;
            }
        }
        return *p1++;
    }

    inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }

    inline void read(int &x) {
        char ch;
        while (blank(ch = nc()));
        if (IOerror) return;
        for (x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
    }

#undef BUF_SIZE
};
using namespace fastIO;
using namespace std;

const int mod = 1e9 + 7;
int n;
int a[5004];
unordered_map<int, int> mp;
int dp[5004][5004];
int cnt = 0;

int main() {
    read(n);
    for (int i = 1; i <= n; ++i) {
        read(a[i]);
    }
    sort(a + 1, a + 1 + n);
    memset(dp, 0, sizeof(dp));
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j < i; ++j) {
            int d = a[i] - a[j];
            int pos = lower_bound(a + 1, a + 1 + n, a[j] - d) - a;
            if (pos < n + 1 && a[pos] == a[j] - d) {
                dp[i][j] = dp[j][pos] + 1;
                ans = max(ans, dp[i][j]);
            } else {
                dp[i][j] = 2;
                ans = max(ans, dp[i][j]);
            }
        }
    }
    cout << ans << endl;
}

猜你喜欢

转载自blog.csdn.net/qq_42671946/article/details/89842885
今日推荐