The Number of Products Gym - 102348F

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循环都简单 但是想出来还是很不易的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值