原题链接:Problem - 1215B - Codeforces
题目大意:
给你n个数,有正有负但是没有为0的,让你求出所有的l <= r的连续区间的al * al + 1 * ...*ar为负数和整数的区间总数分别是多少。
1.其实就看负数的个数是奇数还是偶数就可以了,但是我一开始是前缀和然后两重循环,当然超时了。之后看了网上的博客,有一个写的好好,还是我太菜了;
2.dp[i]表示以i下标结尾的区间的个数,dp[i][0]表示以i为右端点的负数区间的个数,dp[i][1]表示以i为右端点的正数区间的个数;
3.再想想,其实dp[i][0]和dp[i][1]可以由dp[i - 1][0]、dp[i - 1][1]和a[i]推出:
if(a[i] > 0){dp[i][1] = dp[i - 1][1] + 1;dp[i][0] = dp[i - 1][0];}else{dp[i][0] = dp[i - 1][1] + 1;dp[i][1] = dp[i - 1][0];}
参考:Codeforces B. The Number of Products(递推)_HOGWARTS333的博客-CSDN博客
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ios ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
typedef pair<int, int> PII;
const double pi = acos(-1.0);
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for (int i = n; i >= (1); --i)
typedef long long ll;
#define sqar(x) ((x)*(x))const int N = 2e5 + 10;
int dp[N][2]; //以i为右端点的区间有多少个负数区间(dp[i][0]:负数区间个数,dp[i][1]:正数区间个数)int main(){int n, temp;ll ans = 0;ll cnt1 = 0, cnt2 = 0;cin >> n;rep(i, n){cin >> temp;if(temp > 0){dp[i][1] = dp[i - 1][1] + 1;dp[i][0] = dp[i - 1][0];}else{dp[i][0] = dp[i - 1][1] + 1;dp[i][1] = dp[i - 1][0];}cnt1 += dp[i][0];cnt2 += dp[i][1];}cout << cnt1 << " " << cnt2;return 0;
}