早年省选题选做
很多年前的省选题,比较套路。
BJOI2016
P5460 [BJOI2016] IP地址
JSOI2015
P6088 [JSOI2015] 字符串树
解法一:链查询,第一反应肯定是树链剖分。但是不太能写个线段树套 Tire 吧。我们考虑将询问拆分成 \(\log n\) 个放到 dfs 序区间上,然后容斥一步 \([l,r]=[1,r]-[1,l-1]\),这样子只需要最后离线扫描线,向 Trie 中动态加入字符串即可。
解法二:可以用 hash 判断字符串相等,同样转化为树链剖分。
FJOI2016
P4587 [FJOI2016] 神秘数
考虑暴力求一个集合内的神秘数,先将这个集合内的数升序排序。扫描这个序列,设当前值域为 \([1,S]\),如果 \(a_i \le S+1\),那么可以将值域扩展为 \([1,S+a_i]\)。这么做时间复杂度为 \(O(nm\log n)\)。我们发现无法避免掉扫描这个过程,因为这个过程不像二分那样具有单调性,一旦中间有一个地方不满足就要推出。
既然避免不掉扫描,这里不妨转变一下思路既然对于下标扫描会超时,那么我们可以尝试对于值域扫描。如果当前值域为 \([1,val]\),那么 \(ans=val+1\)。尝试对于区间内所有小于 \(ans\) 的值求和,得到的结果 \(sum\),如果 \(sum\ge ans\),显然就是因为有数没有选上,直接选上即可。然后 \(ans \gets sum+1\),继续这个过程。分析一下时间复杂度,我们发现 \(ans\) 的增长下界是类似于斐波那契数列的,于是这是 \(O(\log(\sum a_i))\) 级别的。
HNOI2016
Day1 怕不是莫队场??前两题都是可以用莫队解决的。
P3245 [HNOI2016] 大数
看似字符串,实则区间询问题。我们可以用莫队来解决。
但是这种整除不具有可算性,很难刻画。
考虑维护 \(s_i\) 表示 \([i,n]\) 里面的数字组成的数在 \(\bmod p\) 意义下的值,通过递推很容易求解。
然后想要通过 \(s_i\) 得到 \(\overline{a_l,a_{l+1}...a_r} \bmod p\) 的结果,就可以通过类似字符串哈希的处理方法进行区间转后缀相减。于是 \(s_l \equiv s_{r+1} \bmod p\) 即可,莫队维护。
同时注意当 \(p=2/5\) 的时候,要单独讨论,因为上述方法推导的时候要 \(\times 10\),这会造成 \(\bmod 2/5\) 意义下的错误,根据两者末尾数字的特征判断即可。
P3246 [HNOI2016] 序列
\(O(n\sqrt n)\) 的离线莫队是显然的。
这里有一个 \(O(n\log n)\) 的在线算法。
考虑通过最小值乘以区间长度快速求解。显然从每个点出发都有一个前缀序列,\(pre_x\) 表示最大的 \(y < x\),满足 \(a_y<a_x\)。这些可以通过单调栈求解。于是 \([y+1,x]\) 这一段的贡献便是 \(a_x\)。我们可以用这些区间拼凑出答案区间。
设 \(f_R\) 表示 \([1,R],[2,R]...[R,R]\) 的区间贡献,注意因为要统计所有子区间的贡献,所以这里设 \(f\) 必须表示多个区间的和,否则后面难以计算多个子区间。\(f\) 可以用过递推求解,\(f_R=f_{pre_R}+(R-pre_R)\times a_R\)。我们并不需要计算从 \(1\) 开始的值,所以要做一个类似前缀相减的东西。
减去的贡献是 \([1,R]...[x,R]\),如何选取 \(x\) 就很重要了,这里我们取 \(x\) 为询问区间最小值的位置,这样子 \([1,R]...[x,R]\) 就等价于 \([1,x]...[x,x]\),也就是 \(f_x\),所以 \([x+1,R]...[R,R]\) 的贡献就是 \(f_R-f_x\)。
询问区间为 \([l,r]\),假设最小值的位置是在 \(x\) 处,那么贡献了 \(a_x \times (r-x+1) \times (x-l+1)\)。然后求解 \([l,x-1]\) 和 \([x+1,r]\) 贡献。\([x+1,r]\) 的贡献就是 \(\sum\limits_{i=x+1}^r f_i-f_x\)。\([l,x-1]\) 同理。
TJOI2017
P3760 [TJOI2017] 异或和
异或题考虑拆位计算。先进行前缀和 \(\{s_n\}\),假设在处理第 \(k\) 位,我们可以扫描所有数,扫到第 \(i\) 的数的时候就是统计有多少 \(s_i-s_j\) 的第 \(k\) 位为 \(1\)。我们发现这个好像不太能直接通过目前的第 \(k\) 位来直接来算。
研究一下性质,和整数减法一样,应该是从低到高来考虑,影响减法后第 \(k\) 位结果的没有更高位只有 \(0-k\) 位。发现当 \(s_i\) 的第 \(k\) 位为 \(1\) 的时候,\(s_i-s_j\) 的第 \(k\) 位为 \(1\),应该是 \(s_j\) 的第 \(k\) 位为 \(1\) 且 \(s_j\) 的前 \(k\) 位大于 \(s_i\) 的前 \(k\) 位,或者 \(s_j\) 的第 \(k\) 位为 \(0\),但是 \(s_j\) 的前 \(k\) 位小于等于 \(s_i\) 的前 \(k\) 位。对于 \(s_i\) 的第 \(k\) 位为 \(0\) 同理分析即可。