2019CCPC哈尔滨E:数学,思维

题目提交网址(含题解):

www.CodeFun2000.com(http://101.43.147.120/)

最近我们一直在将收集到的机试真题制作数据并搬运到自己的OJ上,供大家免费练习,体会真题难度。现在OJ已录入50+道2023年最新大厂真题,同时在不断的更新。同时,可以关注"塔子哥学算法"公众号获得每道题的题解。


前言:本周比赛的时候做出来的银牌题.赛后补题的时候发现好像正解和我的还是有点差别.而且正解也挺巧妙的.涉及到了一些我之前没掌握的结论.故特此记录一波.

题意:略

传送门:https://vjudge.net/contest/398773#problem/E

思路:

首先逆序O(n)标记下推可求得基向量.这个没问题.

先说我的定理:对序列正序排序,逆序排序.冲突一定连续.

根据以上定理.hash桶装值域.枚举值域.维护前缀和后缀和判一下冲突情况即可.复杂度:

正解思路:

前置题目1:HDU1205: 给你一个序列.问你是否可能将其排列成任意两个相邻的位置值不相同.

鸽巢定理:若出现次数最多的数的次数 ,则一定有解.

简单证明: 将出现次数最多的数排成一排. 若其他的数的个数 n - x >= x - 1. 那么他们可以将出现最多的数完全分隔开.之后将出现次数次多的按同样的方式填.递归下去一定能够填完且合法.

前置题目2:O(n)求序列中出现次数 > 一半 的数.

方法一:位运算

如果A出现次数最多,那么他在二进制上每一位出现的次数也最多.所以统计二进制每一位上的众数(只有0/1).然后做位运算合并即可.复杂度:O(64n).

方法二:摩尔投票法(我们要的)

思想:假设众数贡献为1,非众数贡献为0.则最后总贡献 > 0.

任意选择一个数y,将其当做众数,模拟贡献.当贡献抵消为0时,剩余的数中众数不变

1.若y是众数.那么抵消的数中有一半是y.剩下的数中仍有一半以上是y.

2.否则,抵消的数中 小于等于 一半的数是y.剩下的数中仍有一半以上是y.

不管怎样,的关系在情况1/2后不会发生改变.

    所以根据上述两个特性,进行模拟.逐渐缩小数组范围.最后得到的一定是众数.

plus:如何判断是否存在超过一半的数?

    得到答案后,扫一遍序列确认一下答案出现的次数:若<= n/2则答案不存在.


有了前面两个前置结论之后:

给一个序列,重新排列使得位置映射到原序列上数两两不同的充分必要条件:

出现次数最多的数的次数 

否则冲突的个数为: 2x - n

重点:我们可以将这个问题转化成 HDU1205:将序列长度 *= 2. 然后把位置相对看成位置相邻.得到一样的结论.

所以扫一遍[基序列],利用摩尔投票法O(n)求次数出现次数最多的数即可.

你可能感兴趣的:(2019CCPC哈尔滨E:数学,思维)