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;
    }
    
  • 相关阅读:
    csuoj 1391: Boiling Vegetables
    csuoj 1392: Number Trick
    nyist 78 圈水池
    1393: Robert Hood 旋转卡壳 凸包
    模板 旋转卡壳 凸包
    模板 凸包 旋转卡壳
    ASP.NET Web API2返回值处理流程
    DependencyInjection源码解读之ServiceProvider
    深入研究EF Core AddDbContext 引起的内存泄露的原因
    私有云方案——利用阿里云云解析实现DDNS
  • 原文地址:https://www.cnblogs.com/hulean/p/10952294.html
Copyright © 2011-2022 走看看