Round#835(Div.4)E. Binary Inversions

 题目链接:Problem - E - Codeforces

 题目概述:给一个只含零一的数组。我们可以选择数组内的任意元素,至多执行下列操作一次。(只能选择一个元素执行操作)。操作为:反转你选择的元素(1变为0,0变为1)。

求操作后(可以不执行),数组里能得到的符合下列情况(a_{i}>a_{j}i<j)的组合的数量。

思路:

先处理出每个元素前边有多少个一,后边有多少个零(自身为一或零算上自身)可以用pair来存。前一后零即为符合条件的情况。

这样我们就可以根据每一个一以及它后面的零的个数(根据零道理一样)来求在执行操作前符合条件的组合数量sum。

假设我们要执行操作,我们可以遍历每个元素,求得变化后带来的增量(可能为负增量)的最大值max。具体为:我们令 first为 a[i] 的前缀1的个数,second为后缀的0的个数。对于1变成0,我们的增量为first - 1 -second;对于0 变为 1,我们的增量为 second - 1 - first。 

最后sum减去max即为答案。

注意数据范围,sum 记得开long long

代码:

#include <bits/stdc++.h>
using namespace std;
const int N =2e5+10;
int a[N];
pair<int,int>c[N];
void solve()
{
    int n;
    cin >> n;
    for(int i = 0;i < n;i++)
    {
        cin >> a[i];
    }
    int one = 0,zero = 0;
    for(int i = 0,j = n - 1;i < n&&j >= 0;i++,j--)
    {
        if(a[i]) 
        {
            one ++;
        }
        if(!a[j]) 
        {
            zero ++;
        }
        c[i].first = one;//每个元素前面有多少个一
        c[j].second = zero;//每个元素后边有多少个零
        //若自身为一或零,也算上自身
    }
   
    long long sum = 0;
    for(int i = 0;i < n;i++)
    {
        if(a[i]) sum += c[i].second;//对于每一个一来求和他匹配的零个数
                                    //和就是操作前的匹配数
    }

    long long max = 0;
    for(int i = 0;i < n;i++)//求进行一次操作后能得到的最增量
    {
        if(a[i])
        {
            int t3 = c[i].first - 1 - c[i].second;
            if(max < t3)
            {
                max = t3;
            }
        }
        else
        {
            int t3 =  c[i].second- 1 - c[i].first;
            if(max < t3)
            {
                max = t3;
            }
        }
    }
    sum += max;//操作后得到答案为和加上增量
    cout << sum <<"\n";
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t = 1;
    cin >> t;
    while(t--)
    {
        solve();
    }


    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值