其他分享
首页 > 其他分享> > UOJ NOI Round #6

UOJ NOI Round #6

作者:互联网

暴露真实水平了,我该怎么办???

Day2

A

记 \(F(S)=\sum_{i\in S} a_i\)。

假如能找到两个集合 \(S,T\subseteq [n]\) 使得 \(S\neq T\land F(S)=F(T)\),那么令 \(S\backslash (S\cap T)\) 中的元素为 \(1\),\(T\backslash (S\cap T)\) 中的元素为 \(-1\),其余元素为 \(0\),这样就构造出了一组答案。

由于 \(2^n-1>p\),根据鸽巢原理,总存在一个 \(s\in [0,p)\cap \mathbb{Z}\) 使得有至少两个集合 \(S\) 满足 \(F(S)=s\),所以一定有解。

考虑分治。设 \(\operatorname{solve}(l,r)\) 表示:我们要找一个 \(s\in [l,r]\) 使得存在集合 \(S\neq T\) 满足 \(F(S)=F(T)=s\),且保证 \([l,r]\) 间有解。令 \(mid=\lfloor\frac{l+r}{2}\rfloor\),我们考虑求出有多少个 \(S\) 满足 \(F(S)\in [l,mid]\)。设这个数是 \(cnt\),假如 \(cnt>mid-l+1\),说明 \([l,mid]\) 间一定有解;否则,\((mid,r]\) 间一定有解。

现在我们需要处理 \(O(\log p)\) 次询问,每次问 \(F(S)\) 在某个区间内的 \(S\) 的个数。折半,设 \(t=\lfloor \frac{n}{2} \rfloor\),开始时预处理 \(a_{1\dots t}\) 和 \(a_{(t+1)\dots n}\) 的所有子集和,并从小到大排序,每次询问时,设 \(S=S_1\cup S_2\),有两种情况:\(F(S_1)+F(S_2)\in [l,r]\),以及 \(F(S_1)+F(S_2)-p\in [l,r]\)。对两种情况分别双指针即可。

最后,我们需要对于分治找到的 \(s\),求出两个集合。利用上面折半得到的信息不难求出。

时间复杂度 \(O(2^{\lceil n/2\rceil}\log p)\)。代码实现

标签:折半,lfloor,NOI,cap,mid,集合,UOJ,有解,Round
来源: https://www.cnblogs.com/alan-zhao-2007/p/unr-6-sol.html