最xx的做法是枚举两个维度,看一眼数据范围,显然会超时;仔细思考,对于每一个右下标而言,我们实际上不需要去枚举其所有的左下标,而是可以动态维护好这一信息——有多少个左下标保证乘积为正,多少个保证为负。
故而,可以设计状态如下:dp[i][0]
表示以i为结尾的乘积为正的数量,dp[i][1]
则是为负的乘积数量。状态转移方程也很简单,读代码。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200000 + 10;
int a[N];
int dp[N][2]; // 0 for postive, 1 for negtive
int main(){
memset(dp, 0, sizeof dp);
int n;cin>>n;
for(int i = 0;i<n;i++){
cin>>a[i];
}
ll neg_ans = 0;
ll pos_ans = 0;
for(int i = 0;i<n;i++){
int is_neg = (a[i]<0);
dp[i][is_neg] = 1;
if(i){
if(is_neg){
dp[i][0] += dp[i-1][1];
dp[i][1] += dp[i-1][0];
}
else{
dp[i][0] += dp[i-1][0];
dp[i][1] += dp[i-1][1];
}
}
neg_ans += dp[i][1];
pos_ans += dp[i][0];
}
cout<<neg_ans<<" "<<pos_ans<<endl;
return 0;
}