题目链接:Problem - E - Codeforces
题目概述:给一个只含零一的数组。我们可以选择数组内的任意元素,至多执行下列操作一次。(只能选择一个元素执行操作)。操作为:反转你选择的元素(1变为0,0变为1)。
求操作后(可以不执行),数组里能得到的符合下列情况(且)的组合的数量。
思路:
先处理出每个元素前边有多少个一,后边有多少个零(自身为一或零算上自身)可以用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;
}