zoukankan      html  css  js  c++  java
  • 洛谷 题解 P1908 【逆序对】

    一开始竟然妄想用(n^2)的算法过这题,然而这是不可能的

    所以只好写归并排序来求逆序対惹

    比如将下面两个区间排序

    3 4 7 9     1 5 8 10
    

    首先将右区间的(1)取出,放到(r_k)中,此时 1 是比每个(a_i)中的元素都小,也就是说此时(i)的指针指向(a_1)的位置,此刻得到的逆序对的数量为(4)(r_k)= 1;

    以此类推,直到进行完归并排序,每次合并都会求出逆序对的数目,即(mid-i+1),最后每次将(ans)加上(mid−i+1)即可得到

    直接上代码

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    int a[500010],t[500010];
    long long ans=0;//存逆序对的个数
    inline int read()
    {
    	int tot=0,f=1;
    	char c=getchar();
    	while(c<'0'||c>'9')
    	{
    		if(c=='-')f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9')
    	{
    		tot=(tot<<1)+(tot<<3)+c-'0';
    		c=getchar();
    	}
    	return tot*f;
    }
    inline void midsort(int l,int r)//归并排序
    {
    	if(l==r)return;//只有一个数
    	int mid=(l+r)>>1;//去中间数
    	midsort(l,mid);midsort(mid+1,r);//分开
    	int i=l,j=mid+1,k=l;
    	while(i<=mid&&j<=r)//合并两个序列
    	{
    		if(a[i]<=a[j])t[k++]=a[i++];
    		else
    		{
    			t[k++]=a[j++];
    			ans+=(long long)mid-i+1;//顺便求一波逆序对
    		}
    	}
    	while(i<=mid)t[k++]=a[i++];
    	while(j<=r)t[k++]=a[j++];//把剩下的合进去
    	for(int i=l;i<=r;i++)a[i]=t[i];//复制一遍,以便下一波操作
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	midsort(1,n);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    excel 2003系列
    DataTab转换XML XML转换DataTable 的类[转]
    全角转半角与半角转全角
    Day2
    Day6 && Day7图论
    Day1
    Android为何以及如何保存Fragment实例
    Android应用的本地化及知识拓展之配置修饰符
    Leetcode NO.136 Single Number 只出现一次的数字
    经典排序算法(四) —— Quick Sort 快速排序
  • 原文地址:https://www.cnblogs.com/hulean/p/10952294.html
Copyright © 2011-2022 走看看