CF362C Insertion Sort(前缀和)

给出一个长度为NN的无序序列,序列为00到N-1N1的排列,现在需要你用冒泡排序来将序列排成从小到大有序的序列

你可以执行一次交换两个元素i,j(i eq j,1le ileq n)i,j(i=j,1in),使得执行冒泡排序时,交换相邻元素的次数最少

要你求出交换相邻元素的最少次数和满足交换相邻元素的次数最少的方案数

题解:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5005;
int n;
int a[maxn];
int l[maxn][maxn];
//l(i,j)表示前j个数里大于数字i的个数 
int r[maxn][maxn];
//r(i,j)表示前j个数里小于数字j的个数 
int main () {
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",a+i),a[i]++;
    for (int i=1;i<=n;i++) {
        for (int j=1;j<=n;j++) {
            if (a[j]>i)
                l[i][j]=l[i][j-1]+1;
            else
                l[i][j]=l[i][j-1];
            if (a[j]<i)
                r[i][j]=r[i][j-1]+1;
            else
                r[i][j]=r[i][j-1];
        }
    }
    int num=0;
    for (int i=1;i<=n;i++) num+=l[a[i]][i];
    int Min=num;
    for (int i=1;i<=n;i++) {
        for (int j=i+1;j<=n;j++) {
            int t1=l[a[j]][j-1]-l[a[j]][i];
            int t2=l[a[i]][j-1]-l[a[i]][i];
            int t3=r[a[j]][j-1]-r[a[j]][i];
            int t4=r[a[i]][j-1]-r[a[i]][i];
            Min=min(Min,num-t1+t2+t3-t4+(a[i]<a[j]?1:-1)); 
        }
    }
    int ans=0;
    for (int i=1;i<=n;i++) {
        for (int j=i+1;j<=n;j++) {
            int t1=l[a[j]][j-1]-l[a[j]][i];
            int t2=l[a[i]][j-1]-l[a[i]][i];
            int t3=r[a[j]][j-1]-r[a[j]][i];
            int t4=r[a[i]][j-1]-r[a[i]][i];
            if (Min==num-t1+t2+t3-t4+(a[i]<a[j]?1:-1)) ans++;
        }
    }
    printf("%d %d
",Min,ans);
}
原文地址:https://www.cnblogs.com/zhanglichen/p/13491262.html