首页 > 其他分享 >AcWing 788 逆序对的数量

AcWing 788 逆序对的数量

时间:2023-04-23 22:24:41浏览次数:36  
标签:子列 int 元素 788 mid long 逆序 AcWing

788. 逆序对的数量 - AcWing题库

逆序对,即位置顺序与大小顺序不符的数对,也就是对于一个期望升序的序列Num[],当i<j时,Num[i]>Num[j]

这道题要求求出逆序对的个数,显然在归并排序的过程中我们就是在逐步的消除逆序对,所以我们可以在递归的排序过程中求出逆序对的个数

已知归并排序是通过前后两个子列来进行归并的且通过递归的操作我们已知进行归并的两个子列在其内部都是有序的,因此可以知道,子列内部是不存在逆序对的

所以逆序对的两元素仅分别存在于两个子列中,在有第一子列下标<第二子列下标,可知只有出现第一子列的元素小于第二子列(第二子列的元素大于第一子列)的情况下才会出现逆序对

假设第一子列指针L已经指到了元素A,第二子列的指针R指到了元素B,且此时B<A,则认为此时出现了上述请况

由于第一子列已经升序排列,所以可以知道,B不仅大于A,还大于A到子列尾的所有数,可知道一共mid-L+1个数,因此由B引起的逆序对的数量就为mid-L+1。

而且,在求完一次归并的逆序对后,经过此次归并,由元素A形成的逆序对就消除了,因此不必担心后续的计算会重复

到这里,相信聪明的你已经知道如何求出逆序对的数量了。

最后一点提醒,当当前两个子列的指针指到的当前元素相等的时候,我们务必选择将第一子列的元素移入存储数组而不是第二子列的元素,因为第二子列的元素是引起逆序对的因素,如果将其移出第二子列,可能会导致后续的逆序对数量缺少,而第一子列的移动不会影响

附上AC代码,当然还要注意开long long ,这题的逆序对数量有的会爆int(不开 long long 见祖宗)

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int q[N];
int Temp[N];
long long  Num = 0;
void merge_sort(int p[], int L, int R)
{
    if (L >= R)return;
    int mid = L + R >> 1;
    merge_sort(p, L, mid);
    merge_sort(p, mid + 1, R);
    int l = L; int r = mid + 1;
    int k = 0;
    while (l <= mid && r <= R)
    {
        if (p[l] <= p[r])//这里的等于很重要
            Temp[k++] = p[l++];
        else
        {
            Num += (mid - l + 1);
            Temp[k++] = p[r++];
        }
    }
    while (l <= mid)Temp[k++] = p[l++];
    while (r <= R)Temp[k++] = p[r++];
    for (int j = 0; L <= R; L++, j++)
        p[L] = Temp[j];
}
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", q + i);
    merge_sort(q, 0, n - 1);
    printf("%lld", Num);
}

给出一个错误案例

    if (p[l] < p[r])
            Temp[k++] = p[l++];
        else
        {
            if(p[l]>p[r])
            Num += (mid - l + 1);//这里就是相等时也选择移动第二子列,会使得逆序对数量减少(可能)
            Temp[k++] = p[r++];
        }

 

标签:子列,int,元素,788,mid,long,逆序,AcWing
From: https://www.cnblogs.com/WKWKSL/p/17347941.html

相关文章

  • 序列、排列的全排列的逆序对
    1.题目大意:给一个长度为n的的数组a,n是1到1e5,ai是1到1e5,问a的所有排序的序列的逆序对之和,会有重复的数字出现题目链接:https://ac.nowcoder.com/acm/contest/46597/Etypedeflonglongll;typedeflonglongLL;typedefpair<int,int>pii;typedefunsignedlonglongull;t......
  • 树状数组解决逆序对问题c++
    前言在算法竞赛中,求逆序对是一个常见的问题。逆序对是指在一个数列中,如果存在,且,那么就是一个逆序对。例如,数列中的逆序对有,总共有树状数组树状数组(FenwickTree)是一种高效的数据结构,用于维护数列的前缀和。树状数组的主要优势在于可以快速对数列进行单点更新和区间查询,时间......
  • 数组中的逆序对
    数组中的逆序对在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。示例1:输入:[7,5,6,4]输出:5限制:0<=数组长度<=50000分析:对于数组[7,5,6,4],若要计算其中的逆序对个数,及[7,5],[7,6],[7,4......
  • AcWing 可达性统计(bitset
    可达性统计建图图的存储拓扑排序:DAG(有向无环图),往拓扑排序思考。拓扑排序的目标是将所有节点排序,使得排在前面的节点不能依赖于排在后面的节点。此类问题需要使用bitset优化。bitset在bitset头文件中,它类似数组,并且每一个元素只能是0或1,每个元素只用1bit空间,可看作几个in......
  • 逆序对的数量(Acwing)
     1.首先要想到排序问题中的归并排序来解决此问题;其次我们要看逆序数的定义是i<j&&a[i]>a[j];下面就来模拟一下;1324789567 ......
  • AcWing 第 98 场周赛 ABC
    https://www.acwing.com/activity/content/competition/problem_list/3128/4947.大整数题目大意:给定n,k。输出n个k。输入样例:32输出样例:222#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;typedefpair<LL,LL>PII;constLLMAXN=1e18,MINN=-M......
  • 788. 逆序对的数量
    linkcode#include<bits/stdc++.h>usingnamespacestd;constintN=100010;inta[N];inttp[N];longlongans;voidmerge(intl,intr){ if(l>=r)return; intmid=l+r>>1; merge(l,mid),merge(mid+1,r); inti=l,j=mid......
  • acwing2816. 判断子序列
    linkcode#include<bits/stdc++.h>usingnamespacestd;constintN=100010;inta[N],b[N];intmain(){ intn,m; cin>>n>>m; for(inti=1;i<=n;i++)cin>>a[i]; for(inti=1;i<=m;i++)cin>>b[i]; in......
  • 区间合并 acwing803
    linkcode#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;intmain(){ intn; intans=1,tpr=0; vector<pair<int,int>>v; intl,r; cin>>n; for(inti=1;i<=n;i++){ cin>>l>>r;......
  • 题目 1026: [编程入门]数字逆序输出
    题目描述输入10个数字,然后逆序输出。输入格式十个整数输出格式逆序输出,空格分开样例输入1234567890样例输出0987654321解题思路:1.题目要求是输入十个整数。2.所以我们定义数组长度为10就可以了。3.利用for循环输入与输出。注......