CODEVS-3303-翻转区间
生活随笔
收集整理的這篇文章主要介紹了
CODEVS-3303-翻转区间
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
描述
http://codevs.cn/problem/3303/
分析
本題就是一個普通的通過打標記實現區間翻轉的splay題目. 之前發過翻轉卡片和這個題很像. 這里主要是想仔細分析一下標記的實現以及一些問題. 為后面的維護數列做一些準備工作.
- 首先明確, 為什么可以通過標記的方式記錄翻轉信息.
splay 的一棵子樹代表的就是一個連續的區間, 因為splay是BST, 滿足結點o的左兒子(lc) <= 根節點(o) <= 右兒子(rc). 并且如果o是其父結點的左兒子, rc一定比o的父節點要小; 如果o是其父結點的右兒子, lc一定又比o的父節點要大. 這樣就保證了區間是連續的, 而且這個區間的序列就是這棵子樹的先序遍歷的結果.
- 既然子樹是一個封閉的區間了, 對其打上翻轉標記后就可以表示區間已經被翻轉了. 那么如何標記下傳呢? 首先根結點的左右子樹應該交換一下, 也就是以根結點o為分界點, 比o小的lc交換到比o大的rc上, 比o大的rc交換到比o小的lc上. 接著以左右子結點為根節點分別將標記下傳到左右兩棵子樹上… 層層下傳, 最終實現整個區間的翻轉. 這就是分治的思想. 當然實現中需要時才將標記下傳一步.
- 最后一個問題, 何時進行標記下傳? 標記下傳后如何維護其父結點以及祖先的值?
這里還要分兩種情況, 第一種是自底向上的splay, 這種需要在find()時把遇到的所有結點進行標記下傳,find()會經過到達目標結點的所有結點. 另一種是自頂向下的splay, 需要在splay操作時把根結點和目標所在的子結點標記下傳. 因為既要找到目標結點在根結點的方向(左子樹還是右子樹), 又要找到目標結點在子結點的方向.
而標記下傳后需不需要維護祖先結點的值呢? 其實不需要過多維護, 因為splay操作自帶維護操作——旋轉操作里就有.
代碼
https://code.csdn.net/snippets/608231
總結
以上是生活随笔為你收集整理的CODEVS-3303-翻转区间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BZOJ-1036-树的统计Count
- 下一篇: 学校测试-2015-2-27