纪中第四天(c组)(2)

时间:2022-06-23 09:48:53

题目(2)(最接近神的人)

 破解了符文之语,小 FF 开启了通往地下的道路。 当他走到最底层时, 发现正前方有一扇巨石门,   门上雕刻着一副古代人进行某种活动的图案。而石门上方用古代文写着“神的殿堂“。小FF 猜想里面应该就有王室的遗产了。但现在的问题是如何打开这扇门……           
       仔细研究后, 他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的。 而最聪明的人往往通过一种仪式选拔出来。 仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字, 并让他们进行一种操作, 即交换序列中相邻的两个元素。 而用最少的交换次数使原序列变成不下降序列的人即是下一任智者。
       小 FF 发现门上同样有着 n 个数字。于是他认为打开这扇门的秘诀就是找到让这个序列变成不下降序列所需要的最小次数。但小 FF 不会……只好又找到了你,并答应事成之后与你三七分……

输入

第一行为一个整数 n,表示序列长度
第二行为 n 个整数,表示序列中每个元素。

输出

一个整数 ans,即最少操作次数。

样例输入

4
2 8 0 3

样例输出

3
样例说明:
开始序列为 2 8 0 3, 目标序列为 0 2 3 8,可进行三次操作得目标序列:
1. Swap(8, 0): 2 0 8 3
2. Swap(2, 0): 0 2 8 3
3. Swap(8, 3): 0 2 3 8

数据范围限制

对于 30%的数据 1 <= n <= 10^4.
对于 100%的数据 1 <= n <= 5 * 10^5;
-maxlongint <= A[i ]<= maxlongint .

 思路

这是一道标准的逆序列题,用归并排序即可。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
long long int a[500001],r[500001],ans=0,n;
void gsort(int s,int t)
{
    if(s==t)
    return ;
    int mid=(s+t)/2;
    gsort(s,mid);
    gsort(mid+1,t);
    int i=s,j=mid+1,k=s;
    while(i<=mid&&j<=t)
    {
        if(a[i]<=a[j])
        {
            r[k]=a[i];
            i++;
            k++;
        }
        else
        {
            r[k]=a[j];
            j++;
            k++;
            ans=ans+mid-i+1;
        }
    }
    while(i<=mid)
    {
        r[k]=a[i];
        i++;
        k++;
    }
    while(j<=t)
    {
        r[k]=a[j];
        j++;
        k++;
    }
    for(int i=s;i<=t;i++)
    a[i]=r[i];
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    cin>>a[i];
    gsort(1,n);
    cout<<ans<<endl;
    return 0;
}