两道贪心的交换sequence

题目

首先是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 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到另一边。扫一遍就可以了。

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 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.                                          
posted @ 2012-11-06 22:06  neayo  阅读(210)  评论(0编辑  收藏  举报