简要题意
- 一开始有 $k$ 种生物,每种生物有 $n$ 个属性 $a_{k,1}, a_{k,2}, \cdots, a_{k,n}$。现有以下 $3$ 种操作:
- (1). 给定两个正整数 $x$,$y$。创建一个新生物,此生物的第 $i$ 项属性为 $\max(a_{x,i}, a_{y,i})$。
- (2). 给定两个正整数 $x$,$y$。创建一个新生物,此生物的第 $i$ 项属性为 $\min(a_{x,i}, a_{y,i})$。
- (3). 给定两个正整数 $x$,$y$。输出第 $x$ 个生物的第 $y$ 项属性。
- 新生物的编号获得最小的未使用数字。
- 操作数 $q \leq 10^5$,属性数 $n \leq 10^5$,$k \leq 12$。
题解
注意到 $k$ 很小,而且最终的答案只会在这 $k$ 个生物里面,考虑把 $k$ 作为切入点。
令 $f_{i,mask}$ 为 如果选择的生物的二进制压缩为 $mask$,则此新生物中,是否一定会存在一个属性大于等于 $i$ 号生物的对应属性?
初始化: 枚举 $mask$,注意到如果 $i$ 号生物被选,则 $f_{i, mask}$ 一定为 $1$,否则不确定,为 $0$。
操作 1(取 $\max$): 注意到三个数 $a, b, c$,当且仅当 $c > a$ 且 $c > b$ 才有 $c > \max(a,b)$,故把 $x$,$y$ 的 $f$ 数组看成一个二进制数,则新生物 $\overline{f_{new,1} \cdots f_{new,n}}$ 对应的二进制数即为 $\overline{f_{x,1} \cdots f_{x,n}} ; \text{and} ; \overline{f_{y,1} \cdots f_{y,n}}$
操作 2 推导同理,此处不再赘述。
操作 3(求答案): 先按照那一位原来的从小到大排序,之后考虑每次加进去一个数看看是否一定大于等于这个位置的值(即 $f_{…,…}=1$)。第一个合法的数即为答案。
可以使用 std::bitset
优化上述过程。注意到不同的 $mask$ 只有 $2^k$ 个,故总时间复杂度为 $\mathcal{O}(\frac{q2^k}{w})$,可以通过本题。
代码
1 |
|