首先是xqz的这道排列,记得去年一考排列我就balabala了。。。其实这道只是披着排列的外衣。
我们可以发现,如果把一个数插到前面,我们肯定可以保证它被放到应该放的位置。
那么我们最多移动n-1次,这是最坏情况,可以发现造成这种情况的原因是a的顺序和b的顺序是反的,于是我们可以把问题转化。
视目标序列为一个递增的序列,将下标作为该元素的值,然后在当前序列中将元素赋值为数字对应的下标。
现在问题就变成了在当前序列中找到从第一个元素开始的最长的一个在原序列中是升序的连续的子序列,假设它的长度为k,那么答案即为n-k。
View Code
1 program Neayo; 2 const 3 inf='Permutations.in'; 4 ouf='Permutations.out'; 5 var 6 i,j,k,n:longint; 7 ans:int64; 8 a,b,c:array[0..200001] of longint; 9 procedure init;10 var same:boolean;11 begin12 assign(input,inf);assign(output,ouf);13 reset(input);rewrite(output);14 readln(n);15 same:=true;16 for i:=1 to n do17 read(a[i]);18 for i:=1 to n do19 begin20 read(b[i]);21 c[b[i]]:=i;22 if b[i]<>a[i] then same:=false;23 end;24 if same then writeln(0)25 else begin26 for i:=1 to n do a[i]:=c[a[i]];27 for i:=1 to n-1 do28 if a[i]>a[i+1] then29 begin30 writeln(n-i);31 exit;32 end;33 end;34 close(input);35 end;36 begin37 init;38 close(output);39 end.
mhj的这道题,可以想到如果要搜索每次交换的话不知道要换到什么时候。。。
那么如果这样交换的话: 1 2 0 1 →1 0 2 1 → 1 1 2 0 算是移动一个数的代价都是1吧。
于是我们就可以无视移动0的问题。
从结果来说,最终1和2一定在一个点的两边,0可以忽略。
于是我们可以贪心地枚举这个点啦……ans就是最小的代价,代价就是这个点要交换多少2和1到另一边。扫一遍就可以了。
View Code
1 program Neayo; 2 const 3 inf='pour.in'; 4 ouf='pour.out'; 5 var 6 i,j,k,n,time,havenum1,havenum2,restnum1,restnum2,ans,num1,num2:longint; 7 a:array[0..1000001]of longint; 8 procedure init; 9 begin10 assign(input,inf);assign(output,ouf);11 reset(input);rewrite(output);12 readln(n);13 for i:=1 to n do14 begin15 read(a[i]);16 if a[i]=1 then inc(restnum1);17 if a[i]=2 then inc(restnum2);18 end;19 num1:=restnum1;20 num2:=restnum2;21 close(input);22 end;23 procedure go;24 begin25 ans:=maxlongint;26 for i:=1 to n do27 begin28 if a[i]=1 then29 begin30 inc(havenum1);31 dec(restnum1);32 end;33 if a[i]=2 then34 begin35 inc(havenum2);36 dec(restnum2);37 end;38 if (i>=num1)and(i+num2<=n)and(restnum1+havenum2=num2)and(i+num1<=n)and(restnum2+havenum1