篝火晚会(fire)
【问题描述】
佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小
教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有 n 个同学,
编号从1到n。一开始,同学们按照 1,2,……,n 的顺序坐成一圈,而实际上每个人都有两
个最希望相邻的同学。如何下命令调整同学的次序,形成新的一个圈,使之符合同学们的意
愿,成为摆在佳佳面前的一大难题。
佳佳可向同学们下达命令,每一个命令的形式如下:
(b1, b2,... bm -1, bm)
这里m的值是由佳佳决定的,每次命令m的值都可以不同。这个命令的作用是移动编号
是b1, b2, …… bm -1, bm的这m个同学的位置。要求b1换到 b2的位置上, b2换到b3的位置上, ……,
要求bm换到b1的位置上。
执行每个命令都需要一些代价。我们假定如果一个命令要移动 m 个人的位置,那么这个
命令的代价就是m。我们需要佳佳用最少的总代价实现同学们的意愿,你能帮助佳佳吗?
【输入文件】
输入文件fire.in 的第一行是一个整数n(3 <= n <= 50000),表示一共有n个同学。
其后n行每行包括两个不同的正整数,以一个空格隔开,分别表示编号是1的同学最希望相
邻的两个同学的编号,编号是 2的同学最希望相邻的两个同学的编号,……,编号是n 的同
学最希望相邻的两个同学的编号。
【输出文件】
输出文件fire.out 包括一行,这一行只包含一个整数,为最小的总代价。如果无论怎
么调整都不能符合每个同学的愿望,则输出-1。
【样例输入】
4
3 4
4 3
1 2
1 2
【样例输出】
2
【数据规模】
对于30%的数据,n <= 1000;
对于全部的数据,n <= 50000。
篝火晚会(fire)
看到这个题,分析条件,m个同学的变换(不一定连续,也不一定升序)构成目标序列,该同学直接走到他需要的点上,然后顶掉现在位置上的人就好了,反正最后肯定成环就是了。
那么,我们只需要找到最大的不需要变换的人数,就可以得到最少的需要变换的人数。
思路1,先构建目标序列(两个),然后将这个序列进行n-1次平移,比较,找到max值
时间复杂度O(n^2);
对于这个题的数据范围(50000),显然不行。
那么,我们可以观察到,当这个目标序列平移时,由于初始序列单增,我们做差发现,平移只是使目标序列与原数列对应的差+-1而已,也就是说,差相等永远相等。差为0代表不移动的话,总有一种移法使得所有差中出现次数最多的数都为0;
也就是说,构建好数列,只需要比较一次就好了
详解见下图
依照这种方法,相当于求差的众数出现的次数(注意有两种序列),然后答案为n-max
相信构建序列大家都会~~~不会我也不说了
program ex02; var a,l,r,b,c:array[1..100000] of longint; d:array[-100000..100000] of longint; n,i,j,k,tot,max:longint; v:array[0..100000] of boolean; begin readln(n); for i:=1 to n do readln(l[i],r[i]); k:=1; tot:=1; while v[k]=false do begin a[tot]:=k; v[k]:=true; if v[l[k]] then k:=r[k] else k:=l[k]; inc(tot); end; if tot<n then begin writeln(-1); //for i:=1 to n do write(a[i],' '); halt; end; for i:=1 to n do begin b[i]:=(a[i]-i+n) mod n; inc(d[b[i]]); if d[b[i]]>max then max:=d[b[i]]; end; fillchar(d,sizeof(d),0); for i:=n downto 2 do begin c[i]:=(a[i]-(n-i+2)+n) mod n; inc(d[c[i]]); if d[c[i]]>max then max:=d[c[i]]; end; inc(d[0]); if d[0]>max then max:=d[0]; writeln(n-max); //writeln(max); end.