• [NOIP2013提高组]火柴排队


    题目:洛谷P1966、Vijos P1842、codevs3286。

    题目大意:有两排火柴,每根都有一个高度。设a、b分别表示两排火柴的高度,现在要令$sum(a_i-b_i)^2$最小。现两排火柴已经排成一个序列,求最少交换多少次能满足条件。

    解题思路:首先,只有当最大的对应最大的,次大的对应次大的,以此类推,得到的答案才可能最小。

    然后我们发现,如此分析后,此题的答案与火柴实际长度无关,只要按照原来的大小顺序即可,且只需考虑对一排火柴进行交换即可。

    因此我们对两组数据分别离散,然后通过第一组数据再对第二组数据再离散一遍即可。

    最后其实就是求逆序对了,归并排序即可。

    时间复杂度$O(nlog _2 n)$。

    既然写了归并,还用什么sort(*^__^*)

    C++ Code:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,a[100005],ans,b[100005],c[100005],ys[100005],p[100005];
    void merge(int* a,int l,int r){
    	int i=l,mid=l+r>>1,k=l;
    	int j=mid+1;
    	while(i<=mid&&j<=r){
    		if(a[i]>a[j]){
    			ans=(ans+mid-i+1)%99999997;
    			c[k++]=a[j++];
    		}
    		else
    		c[k++]=a[i++];
    	}
    	while(i<=mid)c[k++]=a[i++];
    	while(j<=r)c[k++]=a[j++];
    	for(i=l;i<=r;++i)a[i]=c[i];
    }
    void mergesort(int* a,int l,int r){
    	if(l!=r){
    		int m=l+r>>1;
    		mergesort(a,l,m);
    		mergesort(a,m+1,r);
    		merge(a,l,r);
    	}
    }
    void merge_sort(int* a,int l,int r){
    	ans=0;
    	mergesort(a,l,r);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    	memcpy(p,a,sizeof p);
    	merge_sort(p,1,n);
    	for(int i=1;i<=n;++i)
    	ys[p[i]]=i;
    	for(int i=1;i<=n;++i)a[i]=ys[a[i]];
    	for(int i=1;i<=n;++i)scanf("%d",&b[i]);
    	memcpy(p,b,sizeof p);
    	merge_sort(p,1,n);
    	for(int i=1;i<=n;++i)
    	ys[p[i]]=i;
    	for(int i=1;i<=n;++i)b[i]=ys[b[i]];
    	for(int i=1;i<=n;++i)
    	ys[a[i]]=i;
    	for(int i=1;i<=n;++i)b[i]=ys[b[i]];
    	merge_sort(b,1,n);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Java设计模式—状态模式
    Java设计模式—备忘录模式
    android AsyncTask介绍
    Android UI线程和非UI线程
    Java设计模式—代理模式
    Java设计模式—命令模式
    <Android 应用 之路> MPAndroidChart~PieChart
    FPGA的EPCS 配置的2种方法 FPGA下载程序的方法(EPCS)
    如何将.sof转换成.jic
    quartus ii工程文件的分析
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7642765.html
Copyright © 2020-2023  润新知