Code P3286 火柴排队 2013年NOIP全国联赛提高组

Code P3286 火柴排队


题目描述 Description

涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:
,其中 ai表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。


输入输出 Input&Output


输入描述 Input Description

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


输出描述 Output Description

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


样例


样例输入 Sample Input

[Sample 1]

4
2 3 1 4
3 2 1 4

[Sample 2]

4
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。

分析

首先有两列数因为要使得火柴之间高度差和最小,那么肯定是第二行的数按照第一行的数的顺序排列,顺序相同才能使高度差和最小,那么我们可以先将两列数都按照从小到大的顺序排序,那么此时的位置就是其对应应在的位置,记录下现在的位置,然后再将一列进行归并排序,求出其逆序对的个数即为最少交换次数,可以通过二分查找的方式来找处其位置,也可以利用一些比较奇葩的方式,例如快排。。。。

如下两份代码,第一份二分查找,第二份快排。。如下

代码如下


(二分查找);

program p3286;
const mp=99999997;
type num=array[1..1000] of longint;
var n,ans,i,j:longint;
    first,num1,num1x,num2,num2x,num3:num;
procedure qsort(i,j:longint;var g:num);
var l,r,mid:longint;
    temp:longint;
begin
 l:=i;
 r:=j;
 mid:=g[(l+r)>>1];
 while l<=r do
  begin
   while g[l]<mid do inc(l);
   while g[r]>mid do dec(r);
   if l<=r then
    begin
     temp:=g[l];
     g[l]:=g[r];
     g[r]:=temp;
     inc(l);
     dec(r);
    end;
  end;
 if l<j then qsort(l,j,g);
 if i<r then qsort(i,r,g);
end;

function binary(x:longint;var g:num):longint;
var i,j,mid:longint;
begin
 i:=1;
 j:=n;
 while i<j do
  begin
   mid:=(i+j+1)>>1;
   if g[mid]>x
    then j:=mid-1
    else i:=mid;
  end;
 exit(g[i]);
end;

procedure merge_sort(l,r:longint);
var k,i,j,mid,temp:longint;
begin
 if l=r then exit;
 mid:=(l+r)>>1;
 merge_sort(l,mid);
 merge_sort(mid+1,r);
 i:=l;
 j:=mid+1;
 k:=i;
 while (i<=mid) and (j<=r) do
  begin
   if first[num1[i]]>first[num1[j]]
    then
     begin
      num3[k]:=num1[j];
      inc(k);
      inc(j);
      ans:=(ans+mid-i+1) mod mp;
     end
    else
     begin
      num3[k]:=num1[i];
      inc(k);
      inc(i);
     end;
  end;
 while i<=mid  do
  begin
   num3[k]:=num1[i];
   inc(k);
   inc(i);
  end;
 while j<=r do
  begin
   num3[k]:=num1[j];
   inc(k);
   inc(j);
  end;
 for i:=l to r do
  num1[i]:=num3[i];
end;

begin
 readln(n);
 for i:=1 to n do
  begin
   read(num1[i]);
   num1x[i]:=num1[i];
  end;
 for i:=1 to n do
  begin
   read(num2[i]);
   num2x[i]:=num2[i];
  end;
 qsort(1,n,num1x);
 qsort(1,n,num2x);
 for i:=1 to n do
  begin
   num1[i]:=binary(num1[i],num1x);
   num2[i]:=binary(num2[i],num2x);
   first[num2[i]]:=i;
  end;
 merge_sort(1,n);
 write(ans mod mp);
end.
评测结果(二分查找)

运行结果
测试点#match1.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#match10.in 结果:AC 内存使用量: 2540kB 时间使用量: 174ms
测试点#match2.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#match3.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#match4.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#match5.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#match6.in 结果:AC 内存使用量: 368kB 时间使用量: 3ms
测试点#match7.in 结果:AC 内存使用量: 492kB 时间使用量: 12ms
测试点#match8.in 结果:AC 内存使用量: 748kB 时间使用量: 28ms
测试点#match9.in 结果:AC 内存使用量: 1260kB 时间使用量: 81ms


奇葩代码(快排找序)

program p3286;
const mp=99999997;
type rec=record
      name,pre,rank:longint;
     end;
     ar=array[1..100000] of rec;
var i,n,ans:longint;
    num1,num2,num3:ar;
    first:array[1..100000] of longint;
procedure qsort(i,j:longint;var num:ar);
var l,r,mid:longint;
    temp:rec;
begin
 l:=i;
 r:=j;
 mid:=num[(l+r)>>1].name;
 while l<=r do
  begin
   while num[l].name<mid do inc(l);
   while num[r].name>mid do dec(r);
   if l<=r then
    begin
     temp:=num[l];
     num[l]:=num[r];
     num[r]:=temp;
     inc(l);
     dec(r);
    end;
  end;
 if l<j then qsort(l,j,num);
 if i<r then qsort(i,r,num);
end;

procedure qsortx(i,j:longint;var num:ar);
var l,r,mid:longint;
    temp:rec;
begin
 l:=i;
 r:=j;
 mid:=num[(l+r)>>1].pre;
 while l<=r do
  begin
   while num[l].pre<mid do inc(l);
   while num[r].pre>mid do dec(r);
   if l<=r then
    begin
     temp:=num[l];
     num[l]:=num[r];
     num[r]:=temp;
     inc(l);
     dec(r);
    end;
  end;
 if l<j then qsortx(l,j,num);
 if i<r then qsortx(i,r,num);
end;
procedure mersort(l,r:longint);
var i,j,k,mid:longint;
begin
 if l=r then exit;
 mid:=(l+r)>>1;
 mersort(l,mid);
 mersort(mid+1,r);
 i:=l;
 k:=l;
 j:=mid+1;
 while (i<=mid) and (j<=r) do
  begin
   if first[num1[i].rank]>first[num1[j].rank]
    then
     begin
      num3[k]:=num1[j];
      inc(k);
      inc(j);
      ans:=(ans+mid-i+1) mod mp;
     end
    else
     begin
      num3[k]:=num1[i];
      inc(k);
      inc(i);
     end;
  end;
 while (i<=mid) do
  begin
   num3[k]:=num1[i];
   inc(k);
   inc(i);
  end;
 while (j<=r) do
  begin
   num3[k]:=num1[j];
   inc(k);
   inc(j);
  end;
 for i:=l to r do
  begin
   num1[i]:=num3[i];
  end;
end;

begin
 readln(n);
 for i:=1 to n do
  begin
   read(num1[i].name);
   num1[i].pre:=i;
  end;
 for i:=1 to n do
  begin
   read(num2[i].name);
   num2[i].pre:=i;
  end;
 qsort(1,n,num1);
 qsort(1,n,num2);
 for i:=1 to n do
  begin
   num1[i].rank:=i;
   num2[i].rank:=i;
  end;
 qsortx(1,n,num1);
 qsortx(1,n,num2);
 for i:=1 to n do
  begin
   first[num2[i].rank]:=i;
  end;
 mersort(1,n);
 write(ans mod mp);
end.
评测结果

运行结果
测试点#match1.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#match10.in 结果:AC 内存使用量: 4076kB 时间使用量: 170ms
测试点#match2.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#match3.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#match4.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#match5.in 结果:AC 内存使用量: 128kB 时间使用量: 1ms
测试点#match6.in 结果:AC 内存使用量: 364kB 时间使用量: 6ms
测试点#match7.in 结果:AC 内存使用量: 624kB 时间使用量: 14ms
测试点#match8.in 结果:AC 内存使用量: 1264kB 时间使用量: 31ms
测试点#match9.in 结果:AC 内存使用量: 2796kB 时间使用量: 79ms


这里写图片描述

这里写图片描述


这里写图片描述


Taylor Swift - Ours

Elevator buttons and morning air
伴随着清晨的空气按下电梯按钮
Stranger silence makes me wanna take the stairs
陌生人的沉默让我很想走楼梯
If you were here we’d laugh about their vacant stares
如果你在这里,我们会一起偷偷的笑着他们空虚的眼神
But right now my time is theirs
但此刻却是我被他们笑的时候
Seems like there’s always someone who disapproves
生活中总是会有人举着反对的牌子
They’ll judge it like they know about me and you
他们会好像特别了解我们一般的评论着
And the verdict comes from those with nothing else to do
而这些评论往往来自于那些无事可做的人
The jury’s out, my choice is you
评审团是他们的,但是我的选择是你
So don’t you worry your pretty little mind
所以一点都不用担心你的那些小想法
People throw rocks at things that shine
人们总是会往那些闪光的东西扔石子
And life makes love look hard
生活总是会让爱情看上去很艰难
The stakes are high, the water’s rough
赌注很高,风险很大
But this love is ours
但是爱情是我们自己的
You never know what people have up their sleeves
你永远不知道人们有什么阴谋诡计
Ghosts from your past gonna jump out at me
你的那些过去总想跳出来找我麻烦
Lurking in the shadows with their lip gloss smiles
擦着唇彩的嘴唇在阴影里隐隐微笑
But I don’t care
但是我不在乎
Cause right now you’re mine
因为此时此刻,你是我的
And you’ll say
你会说
Don’t you worry your pretty little mind
一点都不用担心你的那些小想法
People throw rocks at things that shine
人们总是会往那些闪光的东西扔石子
And life makes love look hard
生活总是会让爱情看上去很艰难
The stakes are high, the water’s rough
赌注很高,风险很大
But this love is ours
但是爱情是我们自己的
And it’s not theirs to speculate if it’s wrong
这不是他们所能猜测的,不论这是错误与否
And your hands are tough but they are where mine belong in
你的手很粗糙,但这是我的手所属的地方
I’ll fight their doubts and give you faith with this song for you
我会与那些怀疑抗争到底,而这首歌就是我给你信心的证明
Cause I love the gap between your teeth
因为我爱你那有缺缝的牙齿
And I love the riddles that you speak
我爱你说的每一个谜语
And any snide remarks from my father about your tattoos will be ignored.
任何我父亲对你纹身的恶评我们都能忽略
Cause my heart is yours
因为我的心属于你
So don’t you worry your pretty little mind
所以一点都不用担心你的那些小想法
People throw rocks at things that shine
人们总是会往那些闪光的东西扔石子
And life makes love look hard
生活总是会让爱情看上去很艰难
So don’t you worry your pretty little mind
所以一点都不用担心你的那些小想法
People throw rocks at things that shine
人们总是会往那些闪光的东西扔石子
But they can’t take what’s ours
但是他们带不走属于我们的爱情
They can’t take what’s ours
他们带不走属于我们的爱情
The stakes are high, the water’s rough
赌注很高,风险很大
But this love is ours
但是爱情是我们自己的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值