Flat Subsequence 题解
思路
一道线段树优化 dp 题。
设 \(dp_i\) 表示以第 \(i\) 个数字结尾的最长选数列长度,则 \(dp_i=\max(dp_i, dp_j)+1\),其中 \(j<i\) 且 \(| a_i-a_j | \leq K\)。
时间复杂度为 \(O(n^2)\)。
代码如下:
int ans = 0;
rep(i, 1, n)
{
dp[i] = 1;
rep(j, 1, i - 1)
if(abs(a[i] - a[j]) <= k)
dp[i] = max(dp[i], dp[j] + 1);
ans = max(ans, dp[i]);
}
cout << ans << endl;
但是 \(n \leq 300000\),会 TLE,考虑优化。
又可发现上述代码中:
rep(j, 1, i - 1)
if(abs(a[i] - a[j]) <= k)
dp[i] = max(dp[i], dp[j] + 1);
这不就是求 \(a_i-k,a_i+k\) 之间的最值呀!
可以用线段树来进行维护,最后记得修改 \(dp_i\) 的值即可。
代码如下
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, l, r) for(int i = l; i <= r; ++ i)
#define per(i, r, l) for(int i = r; i >= l; -- i)
#define me0(a); memset(a, 0, sizeof a);
#define me3(a); memset(a, 0x3f, sizeof a);
#define PII pair<int, int>
const int INF = 0x3f3f3f3f, MOD = 1e9 + 7;
inline void read(int &n)
{
bool w = 0;
char c = getchar();
for(; c < 48 || c > 57; c = getchar())
w = c == 45;
for(n = 0; c >= 48 && c <= 57; c = getchar())
n = n * 10 + c - 48;
n = w ? -n : n;
}
inline void write(int x, char a)
{
char c[40], s = 0;
if(x < 0) putchar(45), x = -x;
for(; x ;) c[s ++] = x % 10, x /= 10;
if(!s) putchar(48);
for(; s -- ;) putchar(c[s] + 48);
putchar(a);
}
const int MAXN = 300001, M = 300000;
#define ls num + num
#define rs num + num + 1
int sum[MAXN << 2], p[MAXN], addans = -INF;
void update(int num) {sum[num] = max(sum[ls] , sum[rs]);}
void ask(int num, int l, int r, int x, int y)
{
if(x <= l && r <= y)
{
addans = max(addans, sum[num]);
return;
}
int mid = (l + r) >> 1;
if(mid >= x) ask(ls, l, mid, x, y);
if(mid < y) ask(rs, mid + 1, r, x, y);
}
void change(int num, int l, int r, int pos, int val)
{
if(l == r)
{
sum[num] = val;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) change(ls, l, mid, pos, val);
else change(rs, mid + 1, r, pos, val);
update(num);
}
int n, k, ans;
int dp[MAXN];
int a[MAXN];
main()
{
read(n); read(k);
rep(i, 1, n) read(a[i]);
rep(i, 1, n)
{
int L = max(0ll, a[i] - k), R = min(M, a[i] + k);
ask(1, 0, M, L, R);
dp[i] = addans + 1;
change(1, 0, M, a[i], dp[i]);
ans = max(ans, dp[i]);
addans = -INF;
}
cout << ans;
}