The Number of Products Gym - 102348F
You are given a sequence a1,a2,…,an consisting of n integers.
You have to calculate three following values:
the number of pairs of indices (l,r) (l≤r) such that al⋅al+1…ar−1⋅ar is negative;
the number of pairs of indices (l,r) (l≤r) such that al⋅al+1…ar−1⋅ar is zero;
the number of pairs of indices (l,r) (l≤r) such that al⋅al+1…ar−1⋅ar is positive;
Input
The first line contains one integer n (1≤n≤2⋅105) — the number of elements in the sequence.
The second line contains n integers a1,a2,…,an (−109≤ai≤109) — the elements of the sequence.
Output
Print three integers — the number of subsegments with negative product, the number of subsegments with product equal to zero and the number of subsegments with positive product, respectively.
Input
5
5 -3 3 -1 0
Output
6 5 4
Input
10
4 0 -4 3 1 2 -4 3 0 3
Output
12 32 11
Input
5
-1 -2 -3 -4 -5
Output
9 0 6
Note
In the first example there are six subsegments having negative products: (1,2), (1,3), (2,2), (2,3), (3,4), (4,4), five subsegments having products equal to zero: (1,5), (2,5), (3,5), (4,5), (5,5), and four subsegments having positive products: (1,1), (1,4), (2,4), (3,3).
写这道题我主要是想记录一下这种积累状态的方法,这道题的意思是找出所有区间种乘积为零 乘积为正 乘积为负 的个数区间必须连续 可以是一个
一般的做法就是套两层for循环,把所有可能的区间全都遍历一遍 再累计 可这道题卡n^2的时间复杂度 没办法只好找优化算法了 刚开始我想定义两个数 保存在某个数前面的正数和负数的数量,这样状态转移也比较容易 但是转念一想我并不能保证某个数前面的数是连续的 所以不可取 又想到可以保存以某个数结束的前面所有区间的正负情况,这样状态转移时也很方便 要注意遇到零时要清零即可
不难想出只有1+2+3+…+n种情况 只要把正负的去掉剩下的就是零的了
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
int main()
{
ll ans1 = 0, ans2 = 0;
ll a1, a2;
ll n, i, f, flag;
ll len_n = 0;
cin >> n;
if (n % 2 != 0)
{
len_n = (n + 1) / 2;
len_n *= n;
}
else
{
len_n = n * (1 + n) / 2;
}
flag = 1;
a1=a2=0;
for (i = 1; i <= n; i++)
{
scanf("%lld", &f);
if (!f)
{
a1=a2=0;
}
else if (f > 0)
{
a1++;
}
else
{
swap(a1, a2);
a2++;
}
ans1+=a1;
ans2+=a2;
}
printf("%lld %lld %lld\n", ans2, len_n-ans1-ans2, ans1);
return 0;
}
这个代码写出来比两层for循环都简单 但是想出来还是很不易的