您的位置:首页 > 其它

NOIP2013火柴排队

2016-07-11 21:44 357 查看


题目描述 Description

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


,其中 ai表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第
i 个火柴的高度。

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


输入描述 Input Description

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

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

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


输出描述 Output Description

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


样例输入 Sample Input

[Sample 1]



2 3 1 4 

3 2 1 4

[Sample 2]



1 3 4 2 

1 7 2 4


样例输出 Sample Output

[Sample 1]

1

[Sample 2]

2


数据范围及提示 Data Size & Hint

【样例1说明】

最小距离是 0,最少需要交换 1 次,比如:交换第 1 列的前 2 根火柴或者交换第 2 列的前 2 根火柴。

【样例2说明】

最小距离是 10,最少需要交换 2 次,比如:交换第 1 列的中间 2 根火柴的位置,再交换第 2 列中后 2 根火柴的位置。

【数据范围】

对于 10%的数据, 1 ≤ n ≤ 10; 

对于 30%的数据,1 ≤ n ≤ 100; 

对于 60%的数据,1 ≤ n ≤ 1,000; 

对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ 2^31 - 1。

暴力:

#include<iostream>

#include<cstdio>

#include<algorithm>

using namespace std;

int n,c[100010],f[100010],ans,t;

struct data{

 int x,cnt;

}a[100010],b[100010];

bool cmp(data q,data p){

 return q.x<p.x;

}

int main(){

 freopen("1.in","r",stdin);

 freopen("plian.out","w",stdout);

 cin>>n;

 for(int i=1;i<=n;i++){

  cin>>a[i].x;

  a[i].cnt=i;

 }

 for(int i=1;i<=n;i++){

  cin>>b[i].x;

  b[i].cnt=i;

 }

 sort(a+1,a+1+n,cmp);

 sort(b+1,b+1+n,cmp);

 for(int i=1;i<=n;i++){

  c[a[i].cnt]=b[i].cnt;

 }

 for(int i;i<=n;i++){

  for(int j=1;j<=n;j++){

   if(c[i]>c[j]){

    t=c[i];

    c[i]=c[j];

    c[j]=t;

    ans++;

    ans%=99999997;

   }

  }

 }

 cout<<ans;

 return 0;

}

//冒泡。。。。

正解:

#include<iostream>

#include<cstdio>

#include<algorithm>

using namespace std;

int n,c[100010],f[100010],ans;

struct data{

 int x,cnt;

}a[100010],b[100010];

bool cmp(data q,data p){

 return q.x<p.x;

}

void merge(int x,int y){

 int m,i,j,k;

 if(x==y)return ;

 m=(x+y)/2;

 merge(x,m);

 merge(m+1,y);

 i=x;j=m+1;k=i;

 for(k=x;k<=y;k++) 

        if((i<=m)&&((j>y)||(c[i]<=c[j]))) 

            f[k]=c[i++]; 

        else{

            f[k]=c[j++];

            ans+=m-i+1;

   ans%=99999997;

        }   

 for(i=x;i<=y;i++)c[i]=f[i];

}

int main(){

 freopen("1.in","r",stdin);

 freopen("match.out","w",stdout);

 cin>>n;

 for(int i=1;i<=n;i++){

  cin>>a[i].x;

  a[i].cnt=i;

 }

 for(int i=1;i<=n;i++){

  cin>>b[i].x;

  b[i].cnt=i;

 }

 sort(a+1,a+1+n,cmp);

 sort(b+1,b+1+n,cmp);

 for(int i=1;i<=n;i++){

  c[a[i].cnt]=b[i].cnt;

 }

 merge(1,n);

 cout<<ans;

 return 0;

}

//归并逆序对!!!

对拍:

#include<algorithm>

#include<iostream>

#include<cstdio>

#include<ctime>

using namespace std;

int main(){

 freopen("1.in","w",stdout);

 srand(time(0));

 int n=1+rand()%100000;

 cout<<n;

 for(int i=1;i<=n;i++){

  int x;

  x=1+rand()%10000000;

  cout<<x;

 }

 for(int i=1;i<=n;i++){

  int x;

  x=1+rand()%10000000;

  cout<<x;

 }

 return 0;

}

ck.bat:

:loop

@echo off

mk_data.exe

match.exe

plian.exe

fc match.out plian.out ||pause

goto loop

 -------------------------------------------------------------------于2016.7.11
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: