两道贪心的交换sequence
首先是xqz的这道排列,记得去年一考排列我就balabala了。。。其实这道只是披着排列的外衣。
我们可以发现,如果把一个数插到前面,我们肯定可以保证它被放到应该放的位置。
那么我们最多移动n-1次,这是最坏情况,可以发现造成这种情况的原因是a的顺序和b的顺序是反的,于是我们可以把问题转化。
视目标序列为一个递增的序列,将下标作为该元素的值,然后在当前序列中将元素赋值为数字对应的下标。
现在问题就变成了在当前序列中找到从第一个元素开始的最长的一个在原序列中是升序的连续的子序列,假设它的长度为k,那么答案即为n-k。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 begin 12 assign(input,inf);assign(output,ouf); 13 reset(input);rewrite(output); 14 readln(n); 15 same:=true; 16 for i:=1 to n do 17 read(a[i]); 18 for i:=1 to n do 19 begin 20 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 begin 26 for i:=1 to n do a[i]:=c[a[i]]; 27 for i:=1 to n-1 do 28 if a[i]>a[i+1] then 29 begin 30 writeln(n-i); 31 exit; 32 end; 33 end; 34 close(input); 35 end; 36 begin 37 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到另一边。扫一遍就可以了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 begin 10 assign(input,inf);assign(output,ouf); 11 reset(input);rewrite(output); 12 readln(n); 13 for i:=1 to n do 14 begin 15 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 begin 25 ans:=maxlongint; 26 for i:=1 to n do 27 begin 28 if a[i]=1 then 29 begin 30 inc(havenum1); 31 dec(restnum1); 32 end; 33 if a[i]=2 then 34 begin 35 inc(havenum2); 36 dec(restnum2); 37 end; 38 if (i>=num1)and(i+num2<=n)and(restnum1+havenum2<ans) then ans:=restnum1+havenum2; 39 if (i>=num2)and(i+num1<=n)and(restnum2+havenum1<ans) then ans:=restnum2+havenum1; 40 end; 41 writeln(ans); 42 end; 43 begin 44 init; 45 go; 46 close(output); 47 end.