• 洛谷【P1908】逆序对


    题目传送门:https://www.luogu.org/problemnew/show/P1908

    所谓逆序对,就是序列中(a[i]>a[j])(i<j)的有序对。

    所以我们在归并排序的时候可以顺便把这个玩意儿的个数求了。

    如果你不知道归并排序是啥,那么就去看看这个:

    https://www.cnblogs.com/AKMer/p/9645807.html

    如果(a[pos1]>a[pos2]),那么([pos1,mid])都将比(a[pos2])大,就会产生(mid-pos1+1)对逆序对。

    区间内部的逆序对我们在递归的时候已经统计完了,所以我们只需要会统计第一个数在([l,mid]),第二个数在([mid+1,r])中的逆序对就可以了。

    时间复杂度:(O(nlogn))

    空间复杂度:(O(n))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define ll long long
    
    const int maxn=5e5+5;
    
    int n;
    ll ans;
    int a[maxn],p[maxn];
    
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    
    void merge_sort(int l,int r) {
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	merge_sort(l,mid);
    	merge_sort(mid+1,r);
    	int pos1=l,pos2=mid+1,pos=l;
    	while(pos1<=mid&&pos2<=r) {
    		if(a[pos1]<=a[pos2])p[pos++]=a[pos1++];
    		else p[pos++]=a[pos2++],ans+=mid-pos1+1;//统计答案
    	}
    	while(pos1<=mid)p[pos++]=a[pos1++];
    	while(pos2<=r)p[pos++]=a[pos2++];
    	for(int i=l;i<=r;i++)a[i]=p[i];
    }
    
    int main() {
        n=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        merge_sort(1,n);
    	printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    使用基本的socket函数
    ODBC、ADO
    MFC开发ActiveX控件的简介
    MFC线程
    系统API函数实现多线程及线程同步
    IP地址控件
    加速键
    属性页对话框
    Tab控件
    树控件
  • 原文地址:https://www.cnblogs.com/AKMer/p/9646541.html
Copyright © 2020-2023  润新知