题目:
题目大意:给定一个数组,寻找 good subarrays 的个数,其中 good subarrays 是原数组的某个子序列,使得它的任何一个数都大于它在子序列中的索引.
算法:动态规划
dp[i] 表示 以 nums[i] 结尾的最长good subarrays 的长度。
x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 |
leftbound | dp[6]=3 |
对于 下标 6 来说, 以 x6 为结尾的最长 good subarrays 的长度为 3,那么对于 x7 来说, 它的最长 good subarrays 不能到 x4 之前,因为如果在 x4 之前了,那么与 dp[6] = 3 会产生矛盾,所以它的左边界只能在 下标4 的右边,而当这个左边界从下标 4 不断往右移动时,我们发现,在x7 之前 和 这个左边界之后的所有元素,他们都一定会满足 good subarrays 的条件。这是因为这些元素的下标会随着这个指针的后移而减小,但本身元素大小不变。
然后,这个指针一直向后移动 ,我们知道 x7 也必须满足条件(因为是以它结尾的),所以我们的指针从 下标4 不断向后移动,找到第一个使 x7 满足条件的位置.
所以我们有 dp[i] = min(dp[i-1] + 1, nums[i]);
AC代码:
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include <numeric>
#include <string>
#define ll long long
void solve() {
ll n; cin >> n;
vector<ll> dp(n + 3, 0);
ll ans = 0;
for (ll i = 1; i <= n; i++) {
ll x; cin >> x;
dp[i] = min(dp[i - 1] + 1, x);
ans += dp[i];
}
cout << ans << "\n";
}
int main(){
ll t; cin >> t;
while (t--) {
solve();
}
}