一道好题。
- 一定要好好读题,不要看漏。
一个非常非常重要的条件是,\(a\) 是一个排列。这就说明可能会有调和级数之类的做法了。
- 考虑怎么处理询问 \([l,r]\) 之类的东西。
有一个普遍的思路,就是 \(ans=sol(r)-sol(l-1)\),但是我们发现并不适用。因此朴素的 \(f_i\) 表示 \(1\sim i\) 的答案就可以了,我们必须再加一维状态,设 \(f(l,r)\) 为起点在 \(l\),终点在 \(r\) 的方案数。
如果我们有了 \(f(l,r)\),那么一次询问 \([ql,qr]\) 是要求 \(\sum_{x\ge ql,y\le qr}f(x,y)\) 的和,其实就是一个二位数点问题。
- 考虑非 \(0\) 的 \(f(l,r)\) 有几个。
因为起点终点固定,那么一定 \(a_l\mid a_r\)。所以合法数量是 \(\sum div(n)\) 个,也就是调和级数 \(\mathcal{O}(n\ln n)\) 级别。
- 对于单个的 \(f(l,r)\),怎么求。
可以固定左端点或者右端点。固定左端点 \(l\) 更加容易,因为合法的右端点 \(r\) 是找到 \(a_l\) 的倍数,而不是找 \(a_r\) 的因数。转移方程是 \(f(l,r)=\sum_{r'<r}f(l,r')[a_{r'}\mid a_r]\)。但是这个又要找因数了,所以考虑把习惯的 pull 改成 push,即对于 \(f(l,r)\) 考虑他的贡献。这样,他对 \(f(l,r')\) 其中 \(a_r\mid a_{r'},r<r'\) 有贡献。
因此我们有了一个 \(\mathcal{O}(n\ln^2n)\) 的做法。
- 二维数点的写法。
可以无脑的全部离线下来排序以后 bit 维护,但是发现其实可以从大到小枚举 \(f(l,r)\) 的 \(l\) 的过程中就把他解决掉,这样常数较小并且空间小、更好写。
因此得到了一个时空较为优秀的做法。
标签:qr,ln,1946,sum,调和级数,CF,端点 From: https://www.cnblogs.com/SFlyer/p/18426051