Dashboard - Codeforces Round #835 (Div. 4) - Codeforces
E. Binary Inversions
题意:给定一个长度为n的0 1串 ,你可以执行以下操作最多一次(可能为0):将 0 翻转 成 1,或将 1 翻转成 0 。求最大逆序对数。
思路:首先求出原串的逆序对的对数。然后可以枚举每一位翻转的贡献,取贡献的最大值,若最大的贡献<0 ,则无需进行该操作输出原串的逆序对数,否则就是原逆序对数+最大贡献。对于每一位的贡献,用前缀和维护即可,0变1的贡献为:后面的0个数-前面1的个数,1变0的贡献为:前面1的个数-后面0的个数。
#include<bits/stdc++.h>
#define int long long
#define PII pair<int,int>
#define ios ios::sync_with_wtdio(false);cin.tie(0);cin.tie(0)
using namespace std;
const int N=2e5+10;
int a[N];
int n;
int psum[N];
int tmp[N];
int b[N];
long long merge_sort(int q[],int l,int r)
{
if(l>=r) return 0;
int mid=(l+r)/2;
int k=0;
long long ans=merge_sort(q,l,mid)+merge_sort(q,mid+1,r);
int i=l,j=mid+1;
while(i<=mid && j<=r)
{
if(q[i]<=q[j]) tmp[k++]=q[i++];
else {
tmp[k++]=q[j++];
ans += mid-i+1;
}
}
while(i<=mid) tmp[k++]=q[i++];
while(j<=r) tmp[k++]=q[j++];
for(int i=l,j=0;i<=r;j++,i++)
q[i]=tmp[j];
return ans;
}
void solve(){
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
b[i]=a[i];
psum[i]=psum[i-1]+a[i];
}
int mx=-1;
int num;
num=merge_sort(b,1,n);
for(int i=1;i<=n;i++){
int q1=psum[i-1];
int e1=n-i-(psum[n]-psum[i]);
if(a[i]==1)mx=max(q1-e1,mx);
else mx=max(e1-q1,mx);
}
if(mx<0) mx=0;
cout << mx+num << endl;
}
signed main(){
int t=1;
cin >> t;
while(t--){
solve();
}
return 0;
}