splay反轉 P3391 文藝平衡樹

2021-07-27 18:33:10 字數 1344 閱讀 2360

首先你要理解splay的旋轉;

其實反轉和treap是一樣的,都是二叉樹的旋轉;

但是treap用隨機數來維護樹高,而slplay用雙旋來維護;

那我們怎麼翻轉這個區間呢?

對於l~r

我們先把l-1旋轉到根節點

再把r+1旋轉到更節點的右兒子;

顯然,這樣樹根的右子節的左子節點點是l~r;

那麼我們只要把這個區間打乙個標記;

一旦我們要訪問這個節點,先交換左右子樹,再把標記下穿;

如果子樹已經有標記就抵消;

這樣就實現了翻轉區間;

然後我們為l-1,r+1不越界,所以我們把整個區間的範圍變化成0~n+2;

這樣的話要注意一些細節問題;

有些心得說說;

在這個樹里,樹的權值(即節點)是一開始的下標;

但是我們維護的時這些下標的順序;

因為順序的變化,所以我們要把節點與節點之間的關係換掉;

但是節點本身不變;

這個就是和以前學的線段樹什麼的不一樣的地方;

所以我們在寫這類二叉搜尋樹的時候,一定要搞清楚。

我們維護的順序是什麼,節點的權值是什麼;

#include

#include

#include

using

namespace

std;

int c[100005][2],fa[100005],size[100005],rev[100005];//c陣列記錄左右兒子,rev就是標記;

int n,m,x,y,z,rt;

void pushup(int x)

void pushdown(int x)

void make(int l,int r,int z)

int mid=l+r>>1;

make(l,mid-1,mid);

make(mid+1,r,mid);

fa[mid]=z;

pushup(mid);

if(mid0]=mid;else c[z][1]=mid;

}int find(int x,int k)

void turn(int x,int &k)

void splay(int x,int &k)

}void rever(int l,int r)

int main()

for(int i=2;i<=n+1;i++)printf("%d ",find(rt,i)-1);

//因為我們一開始建立的0~n+2的區間,用了n+3個位子,第乙個位子的下標是1,但是我們第乙個數是0而不是1,所以-1;

}

P3391 文藝平衡樹(Splay做法)

您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列。其中需要提供以下操作 翻轉乙個區間,例如原有序序列是 5 4 3 2 154321,翻轉區間是 2,4 2,4 的話,結果是 5 2 3 4 152341。includeusing namespace std const int maxn 1...

洛谷P3391 文藝平衡樹 Splay

時間限制1.00s 記憶體限制125.00mb 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列。其中需要提供以下操作 翻轉乙個區間,例如原有序序列是 54321,翻轉區間是 2,4 的話,結果是 52341。第一行兩個正整數 n,m表示序列長度與操作個數。序列中第 i項初始為 i。接下來 ...

P3391 文藝平衡樹

維護序列,有若干翻轉操作,輸出最後序列 帶翻轉標記的平衡樹模板 在翻轉時,查詢第l 1大,和r 1大的元素 此時下標為權值 考慮到交換左右子樹對查詢樹性質的影響,所以不能直接查詢前驅後繼 在r ot at erotate rotate 操作,和查詢k kk大操作下傳標記即可 因為每個元素固定只有乙個...