「ROI 2018 Day 2」无进位加法
「ROI 2018 Day 2」无进位加法
题目大意:
给出二进制数 \(a_1,\ldots a_n\) ,对于 \(b_1\ldots b_n\)
满足 \(a_i\leq b_i\) , \(\bigoplus b_i=\sum b_i\) ,其中 \(\bigoplus\) 为异或和
求 \(\sum b_i\) 最小值
设长度量级为 \(N=\sum len(a_i)\)
\(O(N^2-N^3)\) , 从高到低确定答案的每一个位
枚举当前位为0,下面的位为1,贪心确定是否存在方案
检查一个答案是否合法:
动态维护一个倒序的 \(a_i\) 集合,从高到低考虑每一个位置
1.如果当前位为0:
如果 \(a_i\) 中存在大于等于这一位的数,非法
2.如果当前位为1:
2-1.如果 \(a_i\) 中存在2个当前位为1的数,非法
2-2.如果 \(a_i\) 中存在恰好一个,则将这个1用于这个 \(a_i\) ,并将 \(a_i\) 去掉最高位后放回集合
2-3.不存在,用这个 \(1\) 删除最大的一个 \(a_i\)
实际看来,这个贪心本身效率并不高
\[\ \]
优化1:快速确定答案最高位的可能范围
令 \(B=\max\{ len(a_i)+i-1\}\)
则 \(len(Ans)\in[B,B+1]\)
上下界均可以由上面的贪心模拟得到
\[ \ \]
优化2:快速维护 \(a_i\) 倒序
显然在不断更改的过程中,当前的 \(a_i\) 一定是原先的某一个 \(a_i\) 的一段后缀
考虑将所有这样的后缀排序,为了方便,用每一个最高的1来表示一个合法的后缀
显然可以先按照后缀长度分类,同长度的后缀,按照后缀中下一个1出现的位置排序
也就是一个类似基数排序个过程,额外维护每一个后缀中下一个出现的 \(1\) 所对应的后缀即可
预处理复杂度为 \(O(N\log N)\)
同时,也可以用线段树快速维护插入/删除的排名,得到 \(B\) 的值,单次操作复杂度 \(O(\log N)\)
\[ \ \]
优化3
称满足 \(len(a_i)+i-1=B\) 的 \(i\) 为 \(\text{critical number}\)
令 \(p\) 为最小的 \(\text{critical number}\) ,也就是在贪心过程中第一个出现情况2-1./2-2.的位置
决策答案为 \(B\) 还是为 \(B+1\) ,也就是决策
是用 \(len(a_p)\) 这个位置删除 \(a_p\) 的最高位,还是用 \(len(a_p)+1\) 的位置删除 \(a_p\)
( \([1,p-1]\) 的部分一定会被删掉)
\(\text{intended solution}\) 采用暴力递归来完成确定每一位的这个操作
1 | Function Solve(Limit) Limit为当前可以使用的最高位的1 |
至于复杂度,官方题解给出为 \(O(N)\) 次递归和删除/加入操作,最终复杂度为 \(O(N\log N)\)
1 |
|