[Poj]3657——数学分析+数据结构

[题目大意]
  • 给定Q个询问以及其答案A,每个询问是询问[L,R]中的最小值。求第一次出现矛盾的位置。

[分析题解]
  •  显然,对于前I个中是否有矛盾的谓词是单调的,这样可以二分答案转化为判定性问题。
  • 现在的问题是,给定指定的若干个询问,其是否矛盾,换句话说,其是否可以都被满足。
  • 仔细的分析一下这个问题,可以得到以下的几个结论:
  • 1.对于每一个位置其牧草数目下界为所有包含此位置的区间A值的最大值。
  • 2.由于各个位置上牧草数目唯一,所以某个数目i只能出现在所有A值为i的区间的交集中。
  • 这样的话,我们很自然的就能想到一个染色判定的做法:二分答案M,将前M个询问按照A值从大到小排序,对于每一个值,我们询问交集,染色并集。我们知道其能出现的位置在所有A值为这个值区间的交集中,我们就去交集中找是否有还没有染色的位置,如果没有的话,我们就可以很肯定的说,这些询问是矛盾的。因为我们询问的时候,我们已经将比这个值大的所有值都给染色了,按照结论1,这些被染色的值,是不能够再放置这个值的,否则就会导出矛盾,所以我们要去找其可能放的位置中,是否还能够找到一个空位置来放置。如果可以,然后再将并集所覆盖的区间给染一下色即可。
  • 对线段的查询以及染色很自然地就能想到线段树,因为坐标范围比较大,可以用离散化加速。
  • 不过更厉害的是这道题目可以用并查集来维护染色段。
  • 对于每一个位置,我们开一个结点记录其父亲是谁,如果我们对线段[L,R]染色,我们就将[L..R]这一段都父亲值都设为L,这样不管下次在查找或是染色的时候,假设我们从后向前找,如果我们用到了[L,R]之间的某一个值,我们都可以直接跳到其父亲的位置上去,因为我们知道,中间这一段都是已经染过色的部分。显然,在染色的过程中我们还可以通过将连续的区间或是重叠的区间进行合并来取得更优的复杂度。严格的复杂度分析我并不会,据说是对于每一次二分答案的判定都是近似O(n)的。
  • 这样,这道题就可以比较完美的解决了。用并查集的好处就是代码比较简洁。

[个人代码]额...不要在意了,虽然说用并查集的好处就是代码比较简洁,但是其实是非常挫的。如果想看代码,可以看相关链接。

[相关链接] 
  1.  http://kongjian.baidu.com.cn/lydrainbowcat/blog/item/abd8f2893e5976af0f24445e.html
  2. http://hi.baidu.com/billdu/blog/item/a5f4483c2f9a34e13d6d9748.html

[启发总结]
  1. 灰常好的一道题目,至少我没看题解的话拿他真是没辙。关键在于那条结论1并将问题转化为一个染色问题,这就要求要有比较强的数学分析能力了。
  2. 并查集的妙用。
posted @ 2012-04-19 10:45  PerSeAwe  阅读(553)  评论(0编辑  收藏  举报