Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Rewrite the array as . Since , the offsets satisfy . So the strict array condition becomes a monotone-offset condition.
A row only scores when , which means . So for row , the only useful offsets are . Everything else has weight .
Create weighted points for all useful offsets. The weight is . Now you want the maximum total weight from points with increasing and nondecreasing .
That is weighted LIS in 2D. Process rows and use a Fenwick tree over offsets to query the best previous value among all offsets .
Don’t update the Fenwick tree while still computing the same row. Store all transitions for row , then apply them. Otherwise you illegally choose multiple offsets for one position. Tiny bug, massive faceplant.
Set
Because , we get
which is exactly
Also , so every offset is in
Let
So instead of choosing a strictly increasing array, we choose a nondecreasing offset sequence.
Now look at one score:
This score is positive only if
Since , this is equivalent to
So row has useful offsets only at
All other offsets give score . They can fill space between useful choices, but they never need to be explicitly chosen.
Points and chains
For every useful choice, create a point
with weight
If we choose several positive-scoring positions, they are compatible exactly when their indices increase and their offsets do not decrease:
Skipped indices are harmless: just assign them any offsets between their neighbors. That gives a valid nondecreasing offset sequence.
So the whole problem is now:
Find a maximum-weight chain of points ordered by increasing and nondecreasing .
That’s weighted LIS in 2D. No need to wrestle the original array directly like it owes you lunch money.
DP with Fenwick tree
Process indices .
For a point ,
over all previous rows and offsets .
We need prefix maximum queries over , so use a Fenwick tree storing max DP values.
For each row :
That last step is not optional. If you update immediately, row can use another point from row as its predecessor, which means choosing two values for the same . That’s illegal, and the judge will absolutely not vibe with it.
Why this is exact
Any valid array produces a nondecreasing offset sequence. Every position with positive score gives one point , and those points form a valid chain. So no array can beat the best chain.
Conversely, any valid chain can be expanded into a full nondecreasing offset sequence by filling skipped indices with offsets between their neighboring chosen offsets. The chosen points contribute exactly their weights, and skipped positions may only add more score. So the best chain is attainable.
Complexity
Row contributes
points. Therefore the total number of points is
Each point does one Fenwick query and one update, so the total complexity is
with memory. Since the sum of over tests is at most , this is comfortably fast.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct FenwickMax {
int n;
vector<int> bit;
FenwickMax(int n = 0) { init(n); }
void init(int n_) {
n = n_;
bit.assign(n + 1, 0);
}
void update(int idx, int val) {
for (++idx; idx <= n; idx += idx & -idx) {
bit[idx] = max(bit[idx], val);
}
}
int query(int idx) const {
int res = 0;
for (++idx; idx > 0; idx -= idx & -idx) {
res = max(res, bit[idx]);
}
return res;
}
};
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
int R = m - n;
FenwickMax fw(R + 1);
int ans = 0;
for (int i = 2; i <= n; i++) {
vector<pair<int, int>> updates;
for (int c = 0; c <= R; c += i) {
int x = i + c;
int w = 0;
while (x % i == 0) {
++w;
x /= i;
}
int cur = fw.query(c) + w;
updates.push_back({c, cur});
ans = max(ans, cur);
}
for (auto [c, val] : updates) {
fw.update(c, val);
}
}
cout << ans << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct FenwickMax {
int n;
vector<int> bit;
FenwickMax(int n = 0) { init(n); }
void init(int n_) {
n = n_;
bit.assign(n + 1, 0);
}
void update(int idx, int val) {
for (++idx; idx <= n; idx += idx & -idx) {
bit[idx] = max(bit[idx], val);
}
}
int query(int idx) const {
int res = 0;
for (++idx; idx > 0; idx -= idx & -idx) {
res = max(res, bit[idx]);
}
return res;
}
};
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
int R = m - n;
FenwickMax fw(R + 1);
int ans = 0;
for (int i = 2; i <= n; i++) {
vector<pair<int, int>> updates;
for (int c = 0; c <= R; c += i) {
int x = i + c;
int w = 0;
while (x % i == 0) {
++w;
x /= i;
}
int cur = fw.query(c) + w;
updates.push_back({c, cur});
ans = max(ans, cur);
}
for (auto [c, val] : updates) {
fw.update(c, val);
}
}
cout << ans << '\n';
}
return 0;
}