1 条题解

  • 0
    @ 2021-10-30 8:05:49

    题意

    已知一个序列,求所有逆序对的一个排列,使得依次交换这些位置的数,使得序列单调不降。

    题解

    题目要求交换位置,先考虑如果交换的是值怎么做。

    直接冒泡排序,容易发现每次交换后逆序对个数减一,所以这样可以使序列有序。

    考虑将位置交换改成值交换。

    先将原序列转化为一个排列

    对于样例二,我们把它变成下面这个图:

    然后把这些线映射到左边

    然后会发现,如果旋转之后只看红线,我们交换黑线的位置实际上就是在交换红线的值。

    直接对红线做一下冒泡排序就好了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1005;
    int n,b[N],p[N];
    vector<pair<int,int> > ans;
    struct hzy{int x,id;}a[N];
    int main() {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i].x),a[i].id=i;
        sort(a+1,a+n+1,[](hzy a,hzy b){if(a.x!=b.x)return a.x<b.x;return a.id<b.id;});
        for(int i=1;i<=n;i++)p[a[i].id]=i;//变成排列
        for(int i=1;i<=n;i++)b[p[i]]=i;//转成红线
        for(int i=1;i<n;i++){
            for(int j=1;j<=n-i;j++){
                if(b[j]>b[j+1])ans.emplace_back(b[j+1],b[j]),swap(b[j+1],b[j]);
            }
        }
        printf("%d\n",ans.size());
        for(auto i:ans)printf("%d %d\n",i.first,i.second);
        return 0;
    }
    
    • 1

    信息

    ID
    873
    时间
    2000ms
    内存
    256MiB
    难度
    9
    标签
    递交数
    3
    已通过
    3
    上传者