感觉构造和交互挺像的,都是人类智慧题。
\(\text{I}\). *[JOISC2022] 一流团子师傅
观察到 \(nm\) 是 \(10000\),而询问次数限制是 \(50000\),所以盲猜询问次数为 \(O(nm\log m)\)。
假设加入时优先填充编号小的竹竿,那么能插入的竹竿就具有单调性,可以二分。
接下来考虑判断能否插入竹竿 \(i\)。因为每种颜色的团子数恰好等于总竹竿数,所以若有一个竿子上面有两个团子,其他的竹竿就不能插入 \(m\) 根竹竿。
具体来讲,询问 \([i+1,m]\) 号竹竿上的团子和未被填放的团子,若不能插入 \(m-i\) 根竹竿,说明 \(i\) 号竹竿原本就有团子。这样就可以判断了。
\(\text{II}\). luoguP9916 「RiOI-03」Just a Q. (Easy ver.)
先关注 SubTask3。可以发现,若先询问一次集合 \(S\),再询问集合 \(S\cup T\),此时有 \(Q=\prod_{i\in S}q_i(\prod_{i\in T}q_i+1)\)。
这里惊喜地出现了喜闻乐见的乘法,因为这样就可以很好的判断正负了。
所以考虑维护出前缀的 \(\prod(q_i+1)\),每次新加入一个 \(p\) 就暴力把 \(\prod\) 拆开计算得到新的 \(\prod(q_i+1)\)。
这样询问次数是 \(\Theta(2^{n-1})\) 的,可以通过 SubTask3。进一步思考可以发现:最初加入的 \(q_1+1\) 是没必要的,可以只加入 \(q_1\),这样询问次数就降到了 \(\Theta(2^{n-2})\)。
因为这是交互题,所以考虑分治。
假设现在确定了答案在区间 \([l,r]\) 内,那么只需判断 \([l,mid]\) 的乘积是否为负。
若 \(Q=0\),直接判断即可。
否则就类似地乘上 \(\prod+1\) 来判断正负。
因为只会递归 \(\log\) 层,每层都询问次数都可能会 \(\times2\),所以总询问次数为 \(\Theta(2^{\lceil\log_2n\rceil})\)。
注意一个小细节,因为判断的是 \([l,mid]\),所以 \(mid\) 要取 \(\frac{l+r-1}{2}\)。不然 \(\left|S\right|\) 就会爆炸。
\(\text{III}\). luoguP9918 「RiOI-03」Just a Q. (Hard ver.)
这题询问次数限制非常紧,无法在套用上题 \(\times(q_i+1)\) 的方法。
换一个角度,如果每次查询都乘上 \(+\infty\),那么就不需要管之前的 \(Q\),可以直接判断正负。
若记 \(a=\prod_{i=l}^{mid}q_i,b=\prod_{i=mid+1}^rq_i\),因为 \(a,b\) 一正一负,所以有 \(\max(\left|a\right|,\left|b\right|)>\left|a+b\right|\)。所以在递归下去时给后面的查询都乘上 \(\max(\left|a\right|,\left|b\right|)\) 就可以避免这一步的影响。
具体来讲,每次求出 \(a,a+b\) 的值,并依次判断 \(a,b\) 的正负和 \(\left|a\right|,\left|b\right|\) 的大小,然后递归下去。
询问次数为 \(2\lceil\log_2n\rceil\),\(\left|S\right|\le \lceil1.5n\rceil\)。