I - The Number of Inversions

本文介绍了一种高效的逆序对计数算法,通过合并排序的思想实现,避免了使用冒泡排序带来的超时问题。文章提供了完整的C++代码实现,并强调了在处理大数据集时使用long类型的重要性。

The Number of Inversions


For a given sequence A={a0,a1,...an1}A={a0,a1,...an−1}, the number of pairs (i,j)(i,j) where ai>ajai>aj and i<ji<j, is called the number of inversions. The number of inversions is equal to the number of swaps of Bubble Sort defined in the following program:

bubbleSort(A)
  cnt = 0 // the number of inversions
  for i = 0 to A.length-1
    for j = A.length-1 downto i+1
      if A[j] < A[j-1]
	swap(A[j], A[j-1])
	cnt++

  return cnt

For the given sequence AA, print the number of inversions of AA. Note that you should not use the above program, which brings Time Limit Exceeded.

Input

In the first line, an integer nn, the number of elements in AA, is given. In the second line, the elements aiai (i=0,1,..n1i=0,1,..n−1) are given separated by space characters.

output

Print the number of inversions in a line.

Constraints

  • 1n200,0001≤n≤200,000
  • 0ai1090≤ai≤109
  • aiai are all different

Sample Input 1

5
3 5 2 1 4

Sample Output 1

6

Sample Input 2

3
3 1 2

Sample Output 2

2



这道题的坑点就是,下标以及统计次数sum都要用long类型,而不能用int,不然会WA,我感觉很奇怪,有的题20w的数据int可以放的下,有的却不行,希望大家知道原因的告诉我。

#include<iostream>

using namespace std;

typedef long long ll;

const long maxn=200005;
const ll maxv=1e9+5;

long sum=0;

void Merge(ll*a,long left,long mid,long right)
{
    long n1=mid-left,n2=right-mid;
    ll *L,*R;
    L=new ll [n1+1];R=new ll [n2+1];
    for(long i=0;i<n1;i++)
        L[i]=a[left+i];
    for(long j=0;j<n2;j++)
        R[j]=a[mid+j];
    L[n1]=R[n2]=maxv;
    long m=0,n=0;
    for(long i=left;i<right;i++)
    {
        if(L[m]<=R[n]){a[i]=L[m];m++;}
        else
        {
            sum+=n1-m;
            a[i]=R[n];
            n++;
        }
    }
}

void Merge_Sort(ll*a,long left,long right)
{
    if(left<right-1)
    {
        long mid=(left+right)/2;
        Merge_Sort(a,left,mid);
        Merge_Sort(a,mid,right);
        Merge(a,left,mid,right);
    }
}


int main()
{
    long n;
    ll a[maxn];
    cin>>n;
    for(long i=0;i<n;i++)
        cin>>a[i];
    Merge_Sort(a,0,n);
    cout<<sum<<endl;
    return 0;
}


There is an integer sequence of length n n, denoted as a 1 , a 2 , ⋯ , a n a 1 ​ ,a 2 ​ ,⋯,a n ​ , where the integers in the sequence can only be 0 0 or 1 1, but some positions in the sequence have not yet been determined. Now you want to fill the undetermined positions in the sequence with 0 0 or 1 1 in such a way that the number of inversion pairs is maximized. The number of inversion pairs in a sequence a 1 , a 2 , ⋯ , a n a 1 ​ ,a 2 ​ ,⋯,a n ​ is defined as the number of integer pairs ( i , j ) (i,j) such that 1 ≤ i < j ≤ n 1≤i<j≤n and a i > a j a i ​ >a j ​ . Input The first line contains a positive integer T T ( 1 ≤ T ≤ 10 4 ) (1≤T≤10 4 ), indicating the number of test cases. For each test case, the first line contains an integer n n ( 2 ≤ n ≤ 10 6 ) (2≤n≤10 6 ), representing the length of the sequence. The second line contains a string s s of length n n consisting only of 0, 1, and ?, representing the sequence, where the i i-th character s i s i ​ being ? indicates that a i a i ​ is unknown and needs to be filled in, otherwise it represents a i a i ​ . It is guaranteed that the sum of n n across all test cases does not exceed 2 × 10 6 2×10 6 . Output For each test case, output a single integer on a new line, representing the maximum number of inversion pairs. Examples Inputcopy Outputcopy 4 3 110 3 1?0 4 ???? 7 1?0?0?1 2 2 4 8 Note For the first sample case, the number of inversion pairs in 110 is 2 2. For the second sample case, it can be filled as 100 or 110, both yielding 2 2 inversion pairs. For the third sample case, it can be filled as 1100, resulting in 4 4 inversion pairs. For the fourth sample case, it can be filled as 1100001 or 1101001, both yielding 8 8 inversion pairs.使用Java实现代码
最新发布
09-25
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水能zai舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值