CodeForces 446A. DZY Loves Sequences(最長上升子序列)
阿新 • • 發佈:2020-07-15
題意:給定一個長度為n的序列,可以修改任何一個字元,求修改後最長的單調嚴格上升子序列(必須是連續的)。
分析:\((1 <= n < 10^5)\),資料範圍很大,不能使用\(o(n^2)\)的演算法。所以我們可以從線性角度考慮,一種常見的套路是列舉修改點,然後求最大值。我們只需要分別求出兩端的情況即可,從開頭到結尾的以第i個數結尾的最長上升子序列,和從結尾到開頭的以第i個數開頭的最長上升子序列。然後列舉修改點,只要\(a[i + 1] - a[i] >= 2\),那麼這兩個最長的子序列就可以連線起來,更新答案。
注意除了這種情況,我們還可以不連線起來,這種情況一定不要忘記,這樣也可以更新答案。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; using LL = long long; const int N = 100005; LL a[N]; int f[N]; int f2[N]; int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]); if (n == 1) { puts("1"); } else if (n == 2) { puts("2"); } else { f[1] = 1; for (int i = 2; i <= n; ++i) { f[i] = 1; if (a[i] > a[i - 1]) f[i] = f[i - 1] + 1; } f2[n] = 1; for (int i = n - 1; i >= 1; --i) { f2[i] = 1; if (a[i] < a[i + 1]) f2[i] = f2[i + 1] + 1; } int res = 0; //修改一個 for (int i = 1; i <= n - 1; ++i) { if (a[i] >= a[i + 1]) res = max(res, f[i] + 1); } for (int i = n - 1; i >= 1; --i) { if (a[i] >= a[i + 1]) res = max(res, f2[i + 1] + 1); } for (int i = 2; i <= n - 1; ++i) { if (a[i + 1] - a[i - 1] >= 2) res = max(res, f2[i + 1] + f[i - 1] + 1); } printf("%d\n", res); } return 0; }