这些日志仅供以后防止自己出现过去犯过的错误,起到一个注记的作用。若其他的ACMer觉得有用的话,本人也感到欣慰~
最近一直在练线段树,说说线段树的“染色问题”和“计数问题”。比如POJ的2155,Level 2的一道题,入门二维线段树,这道题一开始被我当成了染色问题。本来想用每个node去记录这一段是0还是1,结果后来发现二维线段树在x维度上标记没法下传。如果你第一维进的node不一样,第二维的情况就全乱了。所以事实证明这个题应该用计数搞。
然后是1151,Level 3的第一题,扫描离散线段树,刚刚费了很大劲终于AC,得到很多exp。 首先就是这个该死的矩形面积。它的表示都是半开半闭的,比如10~12,12代表的那一点其实是开的,真正有效力的是10和11两点,分别表示两段长度为1的小段。不过你又不能把每个线段的右半边全都-1,不然到线段树那里会出乱子。线段树是相当离散的结构,如果按常规的“点树”建树的话,一旦有单段(12~12)这种东西被分出来,你说是给他计1呢还是计0呢?经试验怎么都不对。一个重要经验就是遇到这种问题不要用“点树”而要真正用线段树的第二形态“区间树”。“区间树”和“点树”的区别有如下几条:
1)建树的时候,点树的mid=(s+e)/2, 区间树的mid=s+(e-s)/2,这是为了保证平衡;
2)点树的最终结点为形如1~1的结点,即s==e,而区间树的最终结点为形如2~3的结点,即s+1==e。
3)建树的时候,点树没有重复的点,相邻的节点都是1~2,3~4这样,而区间树为1~2,2~3这样,有重复的,这是因为区间树的右端点是虚的,这也和题目相对应。
4)更新的时候,点树是if(s<=node[p*2].r)进入左子树,而区间树是s<node[p*2].r,右子树也一样,这都是因为区间树中,单独的点是没有意义的。
前段时间还做了3277,也是Level 2的题,离散扫描线入门,一开始用线段树做,把我虐得够呛,也是因为当时不知道线段树的两个形态。这种问题应该选用区间树做。
大约第一篇就这样吧~