被模拟网络流打爆了。
题意简述
给定一个长度为 $n$ 的序列 $a$。
每次可以选出三个数删掉,需要保证左边和右边的都是 $0$,中间的不是 $0$ 且不能是之前删过的数。
求删掉数的最大次数。$n\le 5\times 10^5$。
主要思路
设 $cnt(x)$ 为序列中 $x$ 的数量,那么显然答案上界为 $m=\lfloor{cnt(0)\over 2}\rfloor$。
假设一个位置左边至少有 $m$ 个 $0$,那么其左边一定可以选出一个 $0$ 来合成答案。右边同理。
不难发现每个点总会满足上述性质中的一条,于是可以据此将节点划分为 $L, R$ 两个集合,$L$ 表示满足右边至少有 $m$ 个点的点集,$R$ 反之。
同时不难发现,如果 $L$ 中有数 $x$ 出现至少两次,更右的出现位置更优。$R$ 中同理。
所以对于每种颜色 $x$,仅保留两个节点,记为 $l(x), r(x)$。
考虑网络流建图:
- 源点 $S$ 向每个颜色 $x$ 连一条流量为 $1$ 的边(颜色边);
- $x$ 向 $l(x),r(x)$ 连一条流量为 $1$ 的边;
- $L$ 中每个下标 $i$ 向 $i - 1$ 连边,$R$ 中每个下标 $i$ 向 $i + 1$ 连边,流量均为 $+\infty$;
- 每个 $0$ 向汇点 $T$ 连一条流量为 $1$ 的边(零边)。
此时,该图的最大流就是需要求的答案。
注意到,最大流等于最小割,考虑求解最小割。
显然,我们只会割去颜色边和零边。并且如果颜色边 $x$ 未被割去,则 $l(x)$ 前面的所有零边,$r(x)$ 后面的所有零边都需要被割去。
因此,最小割方案必定为割去一段前缀零边,一段后缀零边,一部分颜色边。
枚举割走的 $L$ 中前缀零边,则对于每一段 $R$ 中的零后缀,割走这一段零边的代价是前缀长度、后缀长度、前后缀中均不存在的颜色数量的和。
不难推出,只需维护一个支持区间减一、全局最值的数据结构即可。
于是做完了,时间复杂度 $O(n\log n)$。
参考代码
1 |
|