非常好题目!
首先我们考虑两条线段 \([l_1,r_1],[l_2,r_2]\) 满足 \(l_1\leq l_2\leq r_2\leq r_1\),如果大的线段选了,那么小的是否选择都无所谓,这样贡献就抵消了。因此,我们可以把包含其它线段的线段去掉,就剩下了一堆不交的线段。
然后考虑一个单次 \(O(n)\) 的 DP 做法:设从前往后走到第 \(i\) 条线段的贡献系数为 \(f_i\),对于后面的与 \(i\) 有交的线段 \(j\),都会使 \(f_j\) 减去 \(f_i\),最后 \(f_y\) 处即为答案。
这个 DP 的形式非常简单。我们考虑用一个区间 \([l,r]\) 以及一个值 \(w\) 表示整一个 DP 状态,表示现在在转移 \(l\),整个 \([l,r]\) 区间内的值都是 \(w\),其余位置没有值。从后面的过程可以看出这样假设是合理的。
初始的时候有 \(l=r=x,w=-1\),然后当我们要转移 \(l\) 的时候,我们找到 \(l\) 能转移到的最右边的点 \(j\),此时显然有 \(j>r\),然后将 \([l+1,j]\) 区间内全部减去 \(w\)。这时 \([l+1,r]\) 区间内的值就变成 \(0\) 了,\([r+1,j]\) 区间内的值变成了 \(-w\),于是可以继续按照这个状态转移。
这个状态的表示方法一个比较好的地方是两个端点几乎是独立的,我们只需要让两个端点分别跳到 \(\leq y\) 的最大端点,然后分类讨论:
- 若 \(l,r\) 均不为 \(y\),则 \(y\) 处的值显然是 \(0\)。
- 若 \(l,r\) 均为 \(y\),则说明中间至少有一个值没有被覆盖到,则答案也是 \(0\)。
- 否则,\(l,r\) 中就恰好有一个为 \(y\),这时我们可以直接通过 \(l,r\) 跳的次数来判断值是 \(1\) 还是 \(-1\)。
因此我们只需要维护一个倍增即可,时间复杂度 \(O((n+q)\log n)\)。理论上可以通过并查集做到 \(O(n\alpha(a))\) 的说。