P7804 [JOI Open 2021] Financial Report
w33z8kqrqk8zzzx33 · · 题解
首先,题目描述过于抽象,本质是求
只有
考虑 dp,其中
-
p_1-j,p_2-p_1,p_3-p_2,\dots,p_x-p_{x-1},i-p_x\le D -
则可以取所有满足条件的
按照
我们维护一个 set 包含所有已经被更新的位置:这些位置上的值均小于
然后用并查集得到
#include <bits/stdc++.h>
using namespace std;
#define all(a) a.begin(), a.end()
#define fi first
#define se second
#define pb push_back
#define mp make_pair
using ll = long long;
using pii = pair<int, int>;
//#define int ll
const int MOD = 1000000007;
int las[300005];
int ufs(int u) {
if (las[u] == -1)
return u;
return las[u] = ufs(las[u]);
}
void conn(int u, int v) {
u = ufs(u), v = ufs(v);
if (u != v)
las[max(u, v)] = min(u, v);
}
int seg[300005 << 2];
void upd(int idx, int l, int r, int u, int v) {
if (!(l <= u && u < r))
return;
if (r - l == 1) {
seg[idx] = v;
return;
}
upd(idx * 2, l, (l + r) / 2, u, v);
upd(idx * 2 + 1, (l + r) / 2, r, u, v);
seg[idx] = max(seg[idx * 2], seg[idx * 2 + 1]);
}
int qry(int idx, int l, int r, int L, int R) {
if (L <= l && r <= R)
return seg[idx];
if (R <= l || r <= L)
return 0;
return max(qry(idx * 2, l, (l + r) / 2, L, R),
qry(idx * 2 + 1, (l + r) / 2, r, L, R));
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
memset(las, -1, sizeof las);
int n, d;
cin >> n >> d;
vector<pii> x(n);
for (int i = 0; i < n; i++)
cin >> x[i].fi, x[i].se = -i;
sort(all(x));
set<int> on;
int ans = 0;
for (auto [_, i] : x) {
i = -i;
auto pos = on.insert(i).fi;
if (pos != on.begin() && *pos - *prev(pos) <= d)
conn(*pos, *prev(pos));
if (next(pos) != on.end() && *next(pos) - *pos <= d)
conn(*pos, *next(pos));
int dp = qry(1, 0, n, ufs(i), i) + 1;
ans = max(ans, dp);
upd(1, 0, n, i, dp);
}
cout << ans << endl;
}