6.16模拟赛赛后总结
赛时历程
上午七点十分拿到题面然后进行通读,略微思考了一下T1和T2的暴力,到T3时就读不懂题了,尝试多读一会儿理解一下,七点半了,打算直接开始暴力。
先敲T1的最基础的 (n^2) 且(a_ile30) 的分数,枚举区间然后对区间和lowbit一次判断即可,这个分数少的可怜,然后用(set)模拟一下大数进位,这个有(n^2logn) 可过且(a_ile10^9)的部分分,这个还调了一会儿,两个部分总共有30分。大约八点十分,开始写T2的暴力,这个暴力就简单明了许多,(n^2)的模拟非常朴素,然后看这个分数的划分,纯 (n^2) 可以稳定拿到的分数是30分,加了剪枝运气好能够过(30000)的,总共有40分,对着暴力卡常,造数据,大概就九点半了。
上一个厕所,回来思考T3的暴力,发现阶乘枚举排列再找最大完美匹配是一个复杂度很高的算法,偏偏这道题的时间限制是1s。
终于是没有打T3的任何算法,怎么写都不能让我在1e8的時間内通过。T1和T2想再优化也感觉难,并不知道怎么优化。
到了比赛结束。
赛后发现
1 得分30+40. 仍然有一道题是0分。
2 今天好好的按顺序来做事情,不过思路跟不上,搞完暴力之后只能陷入思考的漩涡,需要多思考提升思维。
技术总结
T1 是笛卡尔树+hash,首先是一个结论:若(2^x=sumlimits_{i=l}^{r}a_i),那么(xle max{a_l,a_{l+1},...,a_r}+log_2len) ,这个很容易证明,假设每个点都相等,那么最后的和是(2^a*len),不会超过(2^{a+len}).但这个东西似乎不容易想到,也不知道是什么样的经验让人往(x)的取值范围上去想,想到这个之后,我们发现对于一个区间我们经过(log)个枚举就可以判断出是否存在一个(x)能够满足区间的和为一个整次幂,具体来说,如果固定一个点为最大值,枚举(2^x),然后让这个左端点的前缀和加上(2^x)能够找到一个位置p使得前缀和(s[p]=s[l]+2^x),那么这个区间就是满足要求的,为了快速找到这个位置,考虑用hash将前缀和映射到它的位置上,每次枚举答案的时候,在表中查找(s[l]+2^x)出现的位置,这个位置的前缀和的hash值如果和当前的(s[l]+2^x)的hash值相等,那么就代表(l)到这个位置的区间和是(2^x),累计一个(ans)。暴力的枚举依然有(n^2)的复杂度,所以考虑分治,我们每次确定的答案是基于一个区间里的最大值来"抬升"枚举的,所以说考虑跨过一个最大值的区间对答案的贡献,考虑建出笛卡尔树,搞一个大根堆样子的,从顶开始往下走就保证每次的根的值是最大的,然后考虑一个“启发式”的枚举,左右子树哪个小枚举哪个,假设左子树小,那么枚举左端点,然后枚举答案,hash查找位置在右子树的hash值,如果能够找到,ans++,这样做的复杂度就是(O(nlog_2^2n))的。实现上就是建造笛卡尔树和hash的问题了。
T2 是一个分块多项式,暂且只会(n^2)暴力。
T3 是一个结论性的“暴力”。如果知道结论,可以很快的算出每个位置的贡献,场上可以尝试打表,虽然规律挺难发现的(况且我也没打表这个心思)。结论是,第(i)小的数被计算了$ (dfrac{n}{2}!)^2dbinom{i-1}{frac{n}{2}-1}$次。证明比较难。