AGC056C
题面
你需要构造一个长度为 \(n\) 的 \(01\) 串 \(S\),满足给定的 \(m\) 个条件,每个条件形如:
- \(S[l,r]\) 中 \(0,1\) 的个数相等。
并且最小化 \(01\) 串的字典序。
数据范围:\(n\le 10^6,m\le 2\times 10^5,2|(r-l+1)\) 。
题解
首先,如果你把 \(0\) 看成 \(-1\) ,记 \(s_i\) 为前缀和,那么一个条件 \((l,r)\) 就可以表述为约束 \(s_{l-1}=s_r\) 。
此外,约束还有一个 \(s_i\) 本来的限制 \(s_i-s_{i-1}=\pm 1\) 。
但是这又有什么用呢?
这时候就要使用神奇的算法:差分约束!
\(s_{l-1}=s_r\) 就可以变成 \(l-1\) 往 \(r\) 连了边权为 \(0\) 的边。
但我们怎么转换 \(s_i-s_{i-1}=\pm 1\) 这个限制呢?
因为差分约束的形式是 \(a_x-a_y\le z\) ,我们考虑能不能把 \(s_i-s_{i-1}=\pm 1\) 转换成 \(|s_i-s_{i-1}|\le 1\) ,也就是 \((i,i-1,1),(i-1,i,1)\) 。
仔细想一想,发现好像是可以的!
为什么?
因为 \(2|(r-l+1)\) ,所以是不可能出现 \(s_i=s_{i-1}\) 的。
所以可以用dij得到一组解。
但是题目还要求字典序最小,怎么搞?
可以把顺着走看成是选 \(0\) ,逆着走看成是选 \(1\) ,观察最短路的过程,对于一个约束,我们一般会在前一部分顺着走,后一部分逆着走,直接最短路跑出来的解是字典序最大的解,所以我们取反就会变成字典序最小的点。
启发
- 对于 构造 \(01\) 串并且满足一些性质的题,可以往查分约束上想。