题意可以转换成交换任意两个数,使得逆序数的和最大
我们只需要维护这样一个数组b[i][j]:表示数组的第i个数放在第j的位置的逆序数是多少
然后就枚举交换的两个数的位置,维护最小值就可以了
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<time.h>
#include<set>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
#define inf 0x7fffffff
#define lc l,m,index<<1
#define rc m+1,r,index<<01|1
#define max_n 100005
#define mod 1000000007
#define FOR(i,s,t) for(int i=(s);i<=(t);++i)
#define LL long long
int n;
int a[max_n];
int num[max_n];
int b[5005][5005];
map<int,int>M;
int main()
{
while(~scanf("%d",&n))
{
M.clear();
int ans=0;
int aans;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
{
int t=0;
for(int j=0;j<n;j++)
{
if(t==i) t++;
if(j==0)
b[i][j]=0;
else
{
if(a[t]>a[i])
b[i][j]=b[i][j-1]+1;
else
b[i][j]=b[i][j-1];
t++;
}
// printf("b[%d][%d]=%d ",i,j,b[i][j]);
}
// printf("\n");
}
for(int i=0;i<n;i++)
ans+=b[i][i];
aans=ans;
// printf("ans = %d\n",ans);
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
int as=ans;
int x=b[j][j]-b[j][i];
int y=b[i][j]-b[i][i];
as=as-x-((j-i-1)-y);
as=as+(j-i-1)-x+y;
if(a[i]>a[j])
as++;
else if(a[i]<a[j])
as--;
// printf("%d %d as = %d \n",i,j,as);
aans=min(aans,as);
if(M.find(as)==M.end())
M[as]=1;
else
M[as]++;
}
}
printf("%d %d\n",aans,M[aans]);
}
return 0;
}