主页 > 手机  > 

【算法】火柴排队(离散化、归并排序)

【算法】火柴排队(离散化、归并排序)

涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:

∑i=(ai−bi)^2,其中 ai 表示第一列火柴中第 i个火柴的高度,bi表示第二列火柴中第 i个火柴的高度。 

每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。

请问得到这个最小的距离,最少需要交换多少次?

如果这个数字太大,请输出这个最小交换次数对 99,999,997取模的结果。

输入格式

共三行,第一行包含一个整数 n,表示每盒中火柴的数目。 

第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。

第三行有 n个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。

输出格式

输出共一行,包含一个整数,表示最少交换次数对 99,999,997取模的结果。

数据范围

1≤n≤1e5 0≤火柴高度≤2e31-1

输入样例: 4 2 3 1 4 3 2 1 4 输出样例: 1  离散化模板:

把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小

如这一道题就将2e9转化为2e5,节约空间

void work(int a[]){     for(int i=1;i<=n;i++){         p[i]=i;//存放离散化的下标     }     sort(p+1,p+n+1,[&](int x,int y){return a[x]<a[y];});//升序     for(int i=1;i<=n;i++){         a[p[i]]=i;     } }

归并排序模板:

 int merge_sort(int l,int r){//归并排序可以求出逆序对的数量     if(l>=r) return 0;     int mid=(l+r)>>1;     int res=merge_sort(l,mid)+merge_sort(mid+1,r);     int i=l,j=mid+1,k=0;     while(i<=mid&&j<=r){         if(b[i]<b[j]) p[k++]=b[i++];         else{             p[k++]=b[j++];             res=res+mid-i+1;         }      }     while(i<=mid) p[k++]=b[i++];     while(j<=r) p[k++]=b[j++];     for(i=l,j=0;j<k;i++,j++){         b[i]=p[j];     }     return res; }

映射:   #include<iostream> #include<algorithm> #define N 100010 #define MOD 99999997 using namespace std; int n; int a[N],b[N],c[N],p[N]; void work(int a[]){ for(int i=1;i<=n;i++){ p[i]=i;//存放离散化的下标 } sort(p+1,p+n+1,[&](int x,int y){return a[x]<a[y];});//升序 for(int i=1;i<=n;i++){ a[p[i]]=i; } } int merge_sort(int l,int r){//归并排序可以求出逆序对的数量 if(l>=r) return 0; int mid=(l+r)>>1; int res=(merge_sort(l,mid)+merge_sort(mid+1,r))%MOD; int i=l,j=mid+1,k=0; while(i<=mid&&j<=r){ if(b[i]<b[j]) p[k++]=b[i++]; else{ p[k++]=b[j++]; res=(res+mid-i+1)%MOD; } } while(i<=mid) p[k++]=b[i++]; while(j<=r) p[k++]=b[j++]; for(i=l,j=0;j<k;i++,j++){ b[i]=p[j]; } return res; } int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=n;i++){ cin>>b[i]; } work(a),work(b);//将a,b离散化 for(int i=1;i<=n;i++){ c[a[i]]=i;//将a数组中的元素赋值为其下标并存在数组c中 //a数组相当与升序 } for(int i=1;i<=n;i++){ b[i]=c[b[i]];//映射,b数组的值要先去查找a数组所对应的下标值 } cout<<merge_sort(1,n);//归并排序 return 0; }

标签:

【算法】火柴排队(离散化、归并排序)由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【算法】火柴排队(离散化、归并排序)