[IOI2015]teams分组(二维数点+单调栈)
首先可以得到一个\(O((S+n)\log_2n)\)的贪心做法。
考虑到相同的\(K_i\)可以合并在一起询问,因为\(\sum K_i \leq n\)所以不同的\(K_i\)只有\(\sqrt n\)个,
然后对于两个人\([l_i,r_i],[l_j,r_j]\)如果\(l_i,l_j \in [K_i, K_{i+1})\)且\(r_i,r_j \in [K_i, K_{i+1})\),那么这两个人对于这一次询问是没有区别的。
这样压缩后,结合上述贪心,复杂度\(O(s\sqrt n \log_2 n)\)。
正解是考虑直接优化贪心:
把人看成坐标\((l_i,r_i)\)的点,
那么对于一个\(K_i\),它可以选的点,就是以点\((K_i,K_i)\)为右下角的矩形。
我们先给\(K_i\)按从小到大扫描线。
设\(h_i\)表示扫描到\(K_i\),最优方案下,在\((K_{i-1},K_i]\)最小的\(y\)没被选的高度,
\(f_i\)表示剩下多少个没选。
考虑加进一个\(K\),考虑\(h_i<K\)那么这个\(K\)能选的,\(K_i\)一定选不到。
我们搞一个单调栈,维护下降的\(h_i\),这时,我们就弹掉它。
如果\(K>=h_i\),我们可以通过二维数据结构,求出可选的点数目。
然后我们要确定这个\(K\)的\(h\)值。
考虑先填满自己,如果超出\(h[top]\)那么这个\(top\)再怎么样也会小于当前的\(h\),我们把它们两个合并。
这样就的到了一个\(O(s\log_2n+n\log_2n)\)的算法。