博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj2058: [Usaco2010 Nov]Cow Photographs(逆序对)
阅读量:4310 次
发布时间:2019-06-06

本文共 1489 字,大约阅读时间需要 4 分钟。

      题目大意:给出n个数的序列,每次可以交换相邻的两个数,问把序列变成编号i在编号i+1左边,编号1在编号n右边(一个环)最少需要多少步。如:35421最少交换两次变为34512。

      一开始看到这题,只会O(n²),后来仔细想了一下,妙啊,妙不可言。

      首先我们求出逆序对,即为这个序列变成升序排列的最小次数,问题就在于23451这类的怎么求了。突然,灵稽一动,我们只要把1改成6,然后就可以算出23456的答案,即23451的答案。至于方法,就是我们通过原序列逆序对数量减去1产生的逆序对数量,然后加上给序列添加6产生的逆序对数量,就是23451的答案了。接下来同理,把2改成7,于是我们就可以递推出34512的答案了,以此类推算出所有情况的答案。。。总结一下方法就是把上一次算出来的答案减去现在序列里最小数产生的逆序对数量,然后加上给序列添加最大数+1产生的逆序对数量。

      显然,序列里没有一个数比最小数小(一句废话>_<),所以它产生的逆序对数量就是最小数的位置-1;显然,序列里没有一个数比最大数大(两句废话>_<),所以最大数产生的逆序对数量就是这个数后面的数的数量,即n-最大数的位置,也就是ans[i]=ans[i-1]-(pos[i]-1)+(n-pos[i]),然后我们就输出min(ans[i])就行啦。

      妙啊,妙不可言

代码如下:

uses math;var  n,i:longint;  ans,sum:int64;  a,b,c:array[0..1000000]of int64;procedure merge(l,m,r:longint);var  l1,m1,k,i:longint;begin  l1:=l;m1:=m+1;k:=l;  while (l1<=m)and(m1<=r)do  begin    if a[l1]<=a[m1] then    begin      b[k]:=a[l1];      inc(l1);inc(k);    end    else    begin      b[k]:=a[m1];      inc(m1);inc(k);      ans:=ans+m-l1+1;    end;  end;  while l1<=m do  begin    b[k]:=a[l1];inc(l1);inc(k);  end;  while m1<=r do  begin    b[k]:=a[m1];inc(m1);inc(k);  end;  for i:=l to r do a[i]:=b[i];end;procedure sort(l,r:longint) ;var  mid:longint;begin  if l=r then exit;  mid:=(l+r)>>1;  sort(l,mid);  sort(mid+1,r);  merge(l,mid,r);end;begin  readln(n);  for i:=1 to n do  begin    read(a[i]);    c[a[i]]:=i;  end;  sort(1,n);  sum:=ans;  for i:=1 to n do  begin    sum:=sum-(c[i]-1)+(n-c[i]);    ans:=min(ans,sum);  end;  writeln(ans);end.
View Code

 

转载于:https://www.cnblogs.com/Sakits/p/5837039.html

你可能感兴趣的文章
函数-关键参数
查看>>
spring cloud gateway中解决第一次请求失败的问题
查看>>
BZOJ 1660: [Usaco2006 Nov]Bad Hair Day 乱发节( 单调栈 )
查看>>
log4j学习笔记一(简单配置log4j)
查看>>
BZOJ1941: [Sdoi2010]Hide and Seek
查看>>
时序数据库InfluxDb
查看>>
C++ Knowledge series Conversion & Constructor & Destructor
查看>>
NodeJS学习笔记二
查看>>
JS把字符串转换为数字的方法
查看>>
hive的udf创建永久函数
查看>>
线段树标记永久化模板
查看>>
百度地图API显示多个标注点并添加百度样式检索窗口
查看>>
用户故事——老师
查看>>
sgen.exe" exited with code 1.解决方法
查看>>
实验一
查看>>
Ubuntu配置SSH免密码登陆
查看>>
SOA
查看>>
UVA10561 Treblecross 组合游戏/SG定理
查看>>
查询Oracle定时Job
查看>>
root账户不能使用密码只能使用密钥远程登陆
查看>>