C++ 计算O(n)中具有负乘积的子阵列总数

C++ 计算O(n)中具有负乘积的子阵列总数,c++,math,sub-array,C++,Math,Sub Array,在由整数(负、正和零)组成的数组中 任务是查找乘积为负的子阵列的总数 如果我找到所有子阵列,然后检查负积,它将进入O(n^2)。 龙龙n,a[200001],i,neg[200001],j; 长期总负=0//用于存储负元素数的前缀数组 cin>>n; a[0]=0,负[0]=0; 对于(i=1;i>a[i]; 如果(a[i]从第一个值开始:如果它是负的,您会发现其中一个子数组,如果它是正的,您会发现一个子数组具有正和(稍后为零) 然后让我们考虑下一个值:如果是否定的/积极的,你发现了另一个这样

在由整数(负、正和零)组成的数组中
任务是查找乘积为负的子阵列的总数

如果我找到所有子阵列,然后检查负积,它将进入O(n^2)

龙龙n,a[200001],i,neg[200001],j; 长期总负=0//用于存储负元素数的前缀数组 cin>>n; a[0]=0,负[0]=0; 对于(i=1;i>a[i];
如果(a[i]从第一个值开始:如果它是负的,您会发现其中一个子数组,如果它是正的,您会发现一个子数组具有正和(稍后为零)

然后让我们考虑下一个值:如果是否定的/积极的,你发现了另一个这样的子数组。但是,你可以把它们和你迄今为止发现的所有子数组组合起来!

如果找到了np正子数组,如果当前值为正,则得到另一个np正子数组;如果当前值为负,则得到另一个np负数组,与负nn数组的计数类似,只需得到正值为负积的新数组和负值为正积的新数组

零的特殊值:任何子数组中包含的此值都将生成零作为乘积,其他因素是什么都不重要。因此,您可以在这一点上停止,将nn添加到某个总计数中,然后重新开始np和nn为零

在考虑了数组中的所有数字之后,不要忘记将最新计算的nn添加到总和中


现在剩下的就是将这个算法锻造成代码,这就留给你了……如果你在这样做时遇到麻烦,请随意提出一个新问题,提供你迄今为止编写的代码。

我处理这个问题的方法如下:

我们只关心数字的符号,因为我们不需要计算乘法的实际结果,所以我们可以轻松地将输入转换为1和-1,其中如果给定的数组是{1,-2,3},那么每个值分别表示一个正整数和一个负整数,现在是{1,-1,1}

现在解决这个问题的关键是使用前缀乘法数组来跟踪答案,因为[i,j]中的子数组当且仅当前缀[i]*前缀[j]<0时具有负结果,因此:

答案=#负数(前缀*#正数)前缀

< C++算法看起来是这样的:

int main() {
int n,value;
cin>>n;
int positive=1,negative=0,prefix[n]; 
for (int i=0;i<n;i++){
    cin>>value; 
    if (value>0){
        prefix[i]=1; 
    }else{
        prefix[i]=-1; 
    }

    if (i>0){
        prefix[i]*=prefix[i-1]; 
    }

    if (prefix[i]==1){ 
        positive++; 
    }else{
        negative++; 
    }
} 
int answer=negative*positive;
cout<<answer<<endl;
intmain(){
int n,值;
cin>>n;
int正=1,负=0,前缀[n];
对于(int i=0;i>值;
如果(值>0){
前缀[i]=1;
}否则{
前缀[i]=-1;
}
如果(i>0){
前缀[i]*=前缀[i-1];
}
如果(前缀[i]==1){
正++;
}否则{
负++;
}
} 
int答案=负*正;
cout“如果数组包含整数{-1,2,-3},那么它将给出输出4。但是如果数组包含整数{-1,2,-3,0},那么它将按照上述解决方案给出输出6。”。
我已通过限制条件删除了错误,我的代码是“

import java.io.*;
公共类main 1
{
公共静态void main(字符串[]args)引发IOException{
BufferedReader br=新的BufferedReader(新的InputStreamReader(System.in));
int t=Integer.parseInt(br.readLine());
而(t-->0){
int n=Integer.parseInt(br.readLine());
浮动a[]=新浮动[n];
长arr[]=新长[n];
长位=1,负位=0;
字符串str[]=br.readLine().trim().split(\\s+);
对于(int i=0;i0){
arr[i]=arr[i]*arr[i-1];
}
如果(arr[i]==1){
pos++;
}否则{
neg++;
}
}
长ans=(位置*负)%100000007;
系统输出打印LN(ans);
}
}
}

请向我们展示您到目前为止的代码。我不知道这种情况下的时间复杂度,但您可以:1)获得数组大小(比如说
n
);2)找到所有负值;3)让我们开始算法。。。如果你有一个奇数的负值,那么你肯定有一个负积,这与正值的数量无关。所以你必须使用所有正值和所有可能的负数奇数乘法的组合。Stackoverflow恐怕不是一个家庭作业写作服务。向我们展示你做了什么,解释什么不起作用,我们也许能够修复它。如果一个数组有奇数个负数,那么它将有一个负积,如果这有帮助的话?两个观察结果:(1)你的天真解决方案是O(n^3),而不是O(n^2)[你忘记了计算乘积的成本];(2) 考虑动态规划。此外,如果你能写出时间复杂度为O(n^2)的解决方案,那就太好了。
int main() {
int n,value;
cin>>n;
int positive=1,negative=0,prefix[n]; 
for (int i=0;i<n;i++){
    cin>>value; 
    if (value>0){
        prefix[i]=1; 
    }else{
        prefix[i]=-1; 
    }

    if (i>0){
        prefix[i]*=prefix[i-1]; 
    }

    if (prefix[i]==1){ 
        positive++; 
    }else{
        negative++; 
    }
} 
int answer=negative*positive;
cout<<answer<<endl;
import java.io.*;
public class Main1
{
    public static void main(String[] args)throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int t = Integer.parseInt(br.readLine());
        while(t-->0){
            int n = Integer.parseInt(br.readLine());
            float a[] = new float[n];
            long arr[] = new long[n];
            long pos = 1,neg = 0;
            String str[] = br.readLine().trim().split("\\s+");
            for(int i=0;i<n;i++){
                a[i] = Float.parseFloat(str[i]);
            }
            for(int i=0;i<n;i++) {
                if(a[i]==0) {
                    break;
                }
                if(a[i]>0){
                    arr[i] = 1;
                }else{
                    arr[i] = -1;
                }
                if(i>0){
                    arr[i] = arr[i]*arr[i-1];
                }
                if (arr[i]==1){ 
                    pos++; 
                }else{
                    neg++; 
                }
            }
            long ans = (pos*neg)%1000000007;
            System.out.println(ans);
        }
    }
}