题目的意思是给定一个数组,求有多少个子数组满足子数组可以恰好分为若干个"块"
用len[i]表示从i到前面有多少个连续的数等于a[i],例如a[] = {1,1,2,2,2,1},那么len[] = {1,2,1,2,3,1}
显然初始化len[] = {1,1,1,1,1,1},从i
2开始,如果a[i] = a[i - 1],那么len[i] = len[i - 1] + 1
for(int i = 2; i <= n; i ++){
if(a[i] == a[i - 1]) len[i] = len[i - 1] + 1;
}
然后定义dp[i]表示以i位置结尾的所有子数组中满足条件的子数组个数
第i个位置的数为a[i],那么前面a[i]个数字必须为a[i],那么dp[i] = 1 + dp[i - a[i]];如果不满足,那么dp[i] = 0,表示以i位置结尾的所有子数组中没有满足条件的子数组
for(int i = 1; i <= n; i ++){
if(i - a[i] + 1 >= 1 && len[i] >= a[i]) dp[i] = 1 + dp[i - a[i]];
else dp[i] = 0;
ans += dp[i];
}
总代码:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;
void solve(){
int n; cin >> n;
vector<int> a(n + 1), len(n + 1, 1);
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 2; i <= n; i ++){
if(a[i] == a[i - 1]) len[i] = len[i - 1] + 1;
}
vector<int> dp(n + 5, 0);
int ans = 0;
for(int i = 1; i <= n; i ++){
if(i - a[i] + 1 >= 1 && len[i] >= a[i]) dp[i] = 1 + dp[i - a[i]];
else dp[i] = 0;
ans += dp[i];
}
cout << ans << endl;
return ;
}
signed main(){
HelloWorld;
int tt; cin >> tt;
while(tt --) solve();
return 0;
}



京公网安备 11010502036488号