AC3574乘积数量 (区间操作)

该博客介绍了如何利用前缀积解决一个算法问题,即计算一个整数序列中,使得连续子序列乘积为正或负的区间对数量。通过维护前缀积和正负数的统计,可以有效地计算出答案。代码示例展示了如何实现这一方法,主要涉及动态规划和数组操作。
摘要由CSDN通过智能技术生成

给定一个长度为 n 且不包含 0 的整数序列 a1,a2,…,an。

请你计算以下两值:

使得 al×al+1×…×ar 为负的索引对 (l,r)(l≤r) 的数量。
使得 al×al+1×…×ar 为正的索引对 (l,r)(l≤r) 的数量。


CF链接

题意很简单,就是用前缀和来进行处理,准确的说这里是前缀积

题目中只问我们,在索引对中的值是负是正所以说本质上这个数是什么是不重要的,我们只需要考虑他们的正负关系。

我们假设以 i i i结尾的区间:(i-1, i),(i - 2, i)… (0, i)

因为我们求出来前缀积了,那么这些区间的正负就是 S i / S k , k < i S_i / S_k,k < i Si/Sk,k<i是正是负

如果 S i S_i Si是正的

也就是问我们从s0到si - 1之间有多少个数是正的,因为Si是正的,与前面任意选取一个来进行组合都能贡献出答案,所以当前的答案就是加上前面统计的,此时Si是正的,这时候正的个数就要加一;如果统计负数的个数本质上这时候选择这个正数也可以对负数的答案做贡献,因为正数不改变符号

如果 S i S_i Si是负的,也大致同理,详情看代码

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

int n;

int main(){
	cin >> n;
	
	int x;
	int s = 1;
    // p是整数,n是负数
	ll lp = 1, ln = 0; // lp应当从1开始,因为s0是1,这样能保证更新答案
   
	ll rp = 0, rn = 0;
	
	for(int i = 1; i <= n; i++){
		cin >> x;
		if(x < 0) s *= -1;
		if(s > 0) rn += ln, rp += lp, lp++;
		else rp += ln, rn += lp, ln++; 
	}
	
	cout << rn << " " << rp << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值