1 条题解

  • 0
    @ 2024-11-19 9:51:42

    首先,枚举l,rl,r的写法肯定不可取(n最大为2×105)(n最大为 2 \times 10^5)

    很明显可以发现能够影响答案的只有区间内负数的数量。

    用前缀和数组维护当前位置一共有多少负数出现。

    先·计算出l=1时对答案的贡献ans1(正)ans_1(正)ans2()ans_2(负),剩下的分类讨论即可:

    从l=2开始,令前一位对答案的贡献为ans1,ans2ans_1,ans_2(同上):

    如果当前位置负数出现次数为偶数,且当前数为正

    则该位置对答案贡献为ans11ans_1-1,ans2ans_2

    如果当前位置负数出现次数为奇数,且当前数为正

    则该位对答案的贡献为ans2ans_2,ans1ans_1-1。

    其他两种情况同理

    每次维护贡献求值即可

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    int a[200005];
    int b[200005];
    signed main()
    {
    	 int n;
    	 cin >> n;
    	 for(int i=1;i<=n;i++)
    	 {
    		cin >> a[i];
    		if(a[i]<0)
    		a[i]=1;//小于0为1,否者为0
    		else
    		a[i]=0;
    	 }
    	 int ans1=0,ans2=0;
    	 for(int i=1;i<=n;i++)
    	 {
    		 b[i]+=a[i]+b[i-1];//当前位置出现的负数数目
    		 b[i]=b[i]%2;
    		 if(b[i]%2==0)
    		 ans1++;
    		 else
    		 ans2++;
    	 }
    	 int o=ans1,p=ans2;
    	 if(b[1]%2)
    	 p--;
    	 else
    	 o--;
    	 for(int i=2;i<=n;i++) 
    	 {
    
    	   if(a[i]!=b[i])//分类讨论
    	   {
          ans1+=p;
    		  ans2+=o;
    	   } 
    	   else
    	   {
    	    ans1+=o;
    		  ans2+=p;
    	   }
    	    if(b[i]%2)//维护贡献
    	    p--;
    	    else
    	    o--;
    
    	 }
    	 cout<<ans1<<" "<<ans2<<'\n';
    }
    
    • 1

    信息

    ID
    1066
    时间
    1000ms
    内存
    256MiB
    难度
    9
    标签
    (无)
    递交数
    195
    已通过
    8
    上传者