首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

【NOIP2013】火柴排队

如果没有这道题的话我连逆序对是啥都不知道QAQ

原题:

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

,其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。

1 ≤ n ≤ 100,000,0 ≤火柴高度≤ 2^31-1。

 

首先根据距离定义式可以看粗来,让距离最小,就是让第一列中的第k小的火柴和第二列中的第k小的火柴对齐,而且只能相邻的两个交换,这就是个冒泡

冒泡排序中,如果要把序列排成升序,呢么如果存在i<j && a[i]>a[j],呢么a[i]和a[j]一定要交换,因为a[i]要往右走,a[j]要往左走

定义id为a排序前的位置,数组c为a[i].id对应的b[i].id,呢么就是求c中的逆序对个数,即让两列中第k小的火柴对齐需要的最小交换次数

归并求逆序对即可

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 int read(){int z=0,mark=1;  char ch=getchar();
 8     while(ch<'0'||ch>'9'){if(ch=='-')mark=-1;  ch=getchar();}
 9     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
10     return z*mark;
11 }
12 int mo=99999997;
13 int n;
14 struct cdd{int num,id;}a[110000],b[110000];
15 int c[110000];
16 int d[110000],dtou=0;
17 int bowl=0;
18 bool compare(cdd x,cdd y){return x.num<y.num;}
19 void bing(int _left,int _right){
20     int mid=(_left+_right)/2;  dtou=_left-1;
21     int i=_left,j=mid+1;
22     while(i<=mid && j<=_right){
23         if(c[j]<c[i]){  d[++dtou]=c[j++];  bowl=(bowl+mid-i+1)%mo;}
24         else  d[++dtou]=c[i++];
25     }
26     while(i<=mid)  d[++dtou]=c[i++];//序列是单调的,所以后面的肯定也都大于前面的
27     while(j<=_right)  d[++dtou]=c[j++];
28     for(int i=_left;i<=_right;i++)
29         c[i]=d[i];
30 }
31 void gui(int _left,int _right){
32     if(_left<_right){
33         int mid=(_left+_right)/2;
34         gui(_left,mid),gui(mid+1,_right);
35         bing(_left,_right);
36     }
37 }
38 int main(){//freopen("ddd.in","r",stdin);
39     cin>>n;
40     for(int i=1;i<=n;i++)  a[i].num=read(),a[i].id=i;
41     for(int i=1;i<=n;i++)  b[i].num=read(),b[i].id=i;
42     sort(a+1,a+n+1,compare),sort(b+1,b+n+1,compare);
43     for(int i=1;i<=n;i++)  c[a[i].id]=b[i].id;
44     gui(1,n);
45     /*for(int i=1;i<=n;i++)  cout<<c[i]<<" ";
46     cout<<endl;*/
47     cout<<bowl<<endl;
48     return 0;
49 }
View Code

 

posted on 2016-09-21 18:10  cdcq_old  阅读(186)  评论(0编辑  收藏  举报