/*
QUESTION 4: Counting Smooth Difference Subsequences
Problem Statement:
You are given an integer array nums.
A subsequence is called smooth if the differences between adjacent selected
elements never decrease.
For subsequence:
b1, b2, b3, ..., bk
It must satisfy:
b2 - b1 <= b3 - b2 <= b4 - b3 <= ...
Return the number of smooth subsequences having length at least 2.
Hard Constraints:
1 <= n <= 1000
-1e9 <= nums[i] <= 1e9
Answer modulo 1e9 + 7
Example:
nums = [1, 3, 6]
Expected Output:
4
Explanation:
Valid subsequences:
[1, 3]
[1, 6]
[3, 6]
[1, 3, 6]
Brute Force:
Generate all subsequences and check adjacent differences.
Time Complexity:
O(2^n * n)
Optimized Approach:
Let dp[j][i] be the number of valid subsequences ending with nums[j], nums[i].
To append nums[i] after nums[h], nums[j], we need:
nums[j] - nums[h] <= nums[i] - nums[j]
For each middle index j:
- Store all previous differences ending at j.
- Sort them.
- Use prefix sums and binary search to count valid extensions.
Time Complexity:
O(n^2 log n)
Space Complexity:
O(n^2)
*/
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
static const int MOD = 1000000007;
int countValidSubsequences(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> dp(n, vector<int>(n, 0));
long long ans = 0;
for (int j = 0; j < n; j++) {
vector<pair<long long, int>> previous;
for (int h = 0; h < j; h++) {
long long diff = 1LL * nums[j] - nums[h];
previous.push_back({diff, dp[h][j]});
}
sort(previous.begin(), previous.end());
vector<long long> diffs;
vector<int> pref;
for (auto &p : previous) {
diffs.push_back(p.first);
if (pref.empty()) pref.push_back(p.second);
else pref.push_back((pref.back() + p.second) % MOD);
}
for (int i = j + 1; i < n; i++) {
long long curDiff = 1LL * nums[i] - nums[j];
int ways = 1;
int pos = upper_bound(diffs.begin(), diffs.end(), curDiff) - diffs.begin();
if (pos > 0) {
ways = (ways + pref[pos - 1]) % MOD;
}
dp[j][i] = ways;
ans = (ans + ways) % MOD;
}
}
return ans;
}
};
int main() {
Solution sol;
vector<int> nums = {1, 3, 6};
cout << sol.countValidSubsequences(nums) << endl;
return 0;
}
LyoKUVVFU1RJT04gNDogQ291bnRpbmcgU21vb3RoIERpZmZlcmVuY2UgU3Vic2VxdWVuY2VzCgpQcm9ibGVtIFN0YXRlbWVudDoKWW91IGFyZSBnaXZlbiBhbiBpbnRlZ2VyIGFycmF5IG51bXMuCgpBIHN1YnNlcXVlbmNlIGlzIGNhbGxlZCBzbW9vdGggaWYgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gYWRqYWNlbnQgc2VsZWN0ZWQKZWxlbWVudHMgbmV2ZXIgZGVjcmVhc2UuCgpGb3Igc3Vic2VxdWVuY2U6CmIxLCBiMiwgYjMsIC4uLiwgYmsKCkl0IG11c3Qgc2F0aXNmeToKYjIgLSBiMSA8PSBiMyAtIGIyIDw9IGI0IC0gYjMgPD0gLi4uCgpSZXR1cm4gdGhlIG51bWJlciBvZiBzbW9vdGggc3Vic2VxdWVuY2VzIGhhdmluZyBsZW5ndGggYXQgbGVhc3QgMi4KCkhhcmQgQ29uc3RyYWludHM6CjEgPD0gbiA8PSAxMDAwCi0xZTkgPD0gbnVtc1tpXSA8PSAxZTkKQW5zd2VyIG1vZHVsbyAxZTkgKyA3CgpFeGFtcGxlOgpudW1zID0gWzEsIDMsIDZdCgpFeHBlY3RlZCBPdXRwdXQ6CjQKCkV4cGxhbmF0aW9uOgpWYWxpZCBzdWJzZXF1ZW5jZXM6ClsxLCAzXQpbMSwgNl0KWzMsIDZdClsxLCAzLCA2XQoKQnJ1dGUgRm9yY2U6CkdlbmVyYXRlIGFsbCBzdWJzZXF1ZW5jZXMgYW5kIGNoZWNrIGFkamFjZW50IGRpZmZlcmVuY2VzLgoKVGltZSBDb21wbGV4aXR5OgpPKDJebiAqIG4pCgpPcHRpbWl6ZWQgQXBwcm9hY2g6CkxldCBkcFtqXVtpXSBiZSB0aGUgbnVtYmVyIG9mIHZhbGlkIHN1YnNlcXVlbmNlcyBlbmRpbmcgd2l0aCBudW1zW2pdLCBudW1zW2ldLgoKVG8gYXBwZW5kIG51bXNbaV0gYWZ0ZXIgbnVtc1toXSwgbnVtc1tqXSwgd2UgbmVlZDoKbnVtc1tqXSAtIG51bXNbaF0gPD0gbnVtc1tpXSAtIG51bXNbal0KCkZvciBlYWNoIG1pZGRsZSBpbmRleCBqOgotIFN0b3JlIGFsbCBwcmV2aW91cyBkaWZmZXJlbmNlcyBlbmRpbmcgYXQgai4KLSBTb3J0IHRoZW0uCi0gVXNlIHByZWZpeCBzdW1zIGFuZCBiaW5hcnkgc2VhcmNoIHRvIGNvdW50IHZhbGlkIGV4dGVuc2lvbnMuCgpUaW1lIENvbXBsZXhpdHk6Ck8obl4yIGxvZyBuKQoKU3BhY2UgQ29tcGxleGl0eToKTyhuXjIpCiovCgojaW5jbHVkZSA8Yml0cy9zdGRjKysuaD4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmNsYXNzIFNvbHV0aW9uIHsKcHVibGljOgogICAgc3RhdGljIGNvbnN0IGludCBNT0QgPSAxMDAwMDAwMDA3OwoKICAgIGludCBjb3VudFZhbGlkU3Vic2VxdWVuY2VzKHZlY3RvcjxpbnQ+JiBudW1zKSB7CiAgICAgICAgaW50IG4gPSBudW1zLnNpemUoKTsKCiAgICAgICAgdmVjdG9yPHZlY3RvcjxpbnQ+PiBkcChuLCB2ZWN0b3I8aW50PihuLCAwKSk7CiAgICAgICAgbG9uZyBsb25nIGFucyA9IDA7CgogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgbjsgaisrKSB7CiAgICAgICAgICAgIHZlY3RvcjxwYWlyPGxvbmcgbG9uZywgaW50Pj4gcHJldmlvdXM7CgogICAgICAgICAgICBmb3IgKGludCBoID0gMDsgaCA8IGo7IGgrKykgewogICAgICAgICAgICAgICAgbG9uZyBsb25nIGRpZmYgPSAxTEwgKiBudW1zW2pdIC0gbnVtc1toXTsKICAgICAgICAgICAgICAgIHByZXZpb3VzLnB1c2hfYmFjayh7ZGlmZiwgZHBbaF1bal19KTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgc29ydChwcmV2aW91cy5iZWdpbigpLCBwcmV2aW91cy5lbmQoKSk7CgogICAgICAgICAgICB2ZWN0b3I8bG9uZyBsb25nPiBkaWZmczsKICAgICAgICAgICAgdmVjdG9yPGludD4gcHJlZjsKCiAgICAgICAgICAgIGZvciAoYXV0byAmcCA6IHByZXZpb3VzKSB7CiAgICAgICAgICAgICAgICBkaWZmcy5wdXNoX2JhY2socC5maXJzdCk7CgogICAgICAgICAgICAgICAgaWYgKHByZWYuZW1wdHkoKSkgcHJlZi5wdXNoX2JhY2socC5zZWNvbmQpOwogICAgICAgICAgICAgICAgZWxzZSBwcmVmLnB1c2hfYmFjaygocHJlZi5iYWNrKCkgKyBwLnNlY29uZCkgJSBNT0QpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBmb3IgKGludCBpID0gaiArIDE7IGkgPCBuOyBpKyspIHsKICAgICAgICAgICAgICAgIGxvbmcgbG9uZyBjdXJEaWZmID0gMUxMICogbnVtc1tpXSAtIG51bXNbal07CgogICAgICAgICAgICAgICAgaW50IHdheXMgPSAxOwoKICAgICAgICAgICAgICAgIGludCBwb3MgPSB1cHBlcl9ib3VuZChkaWZmcy5iZWdpbigpLCBkaWZmcy5lbmQoKSwgY3VyRGlmZikgLSBkaWZmcy5iZWdpbigpOwoKICAgICAgICAgICAgICAgIGlmIChwb3MgPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgd2F5cyA9ICh3YXlzICsgcHJlZltwb3MgLSAxXSkgJSBNT0Q7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgZHBbal1baV0gPSB3YXlzOwogICAgICAgICAgICAgICAgYW5zID0gKGFucyArIHdheXMpICUgTU9EOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gYW5zOwogICAgfQp9OwoKaW50IG1haW4oKSB7CiAgICBTb2x1dGlvbiBzb2w7CgogICAgdmVjdG9yPGludD4gbnVtcyA9IHsxLCAzLCA2fTsKCiAgICBjb3V0IDw8IHNvbC5jb3VudFZhbGlkU3Vic2VxdWVuY2VzKG51bXMpIDw8IGVuZGw7CgogICAgcmV0dXJuIDA7Cn0=