某巨文藝平衡樹(Splay模板)

2021-09-27 13:40:57 字數 2895 閱讀 2963

洛谷 p3391

/*splay只記模板是很困難的,而且真正運用時易生疏出錯,所以必須理解,在看**前先弄懂

splay的原理,這篇**是帶注釋的splay模板,題目來自洛谷p3391 ———————————by 520*/

#include#define il inline

using namespace std;

const int n = 100005;

il int gi()

int n, m, tot, root, siz[n], fa[n], lazy[n], key[n], tree[n][2], ans[n];

/*root為根節點,siz儲存子樹節點數,fa儲存父節點,lazy是懶惰標記用來標記區間翻轉操作,key陣列儲存原數列,tree為

splay樹,ans儲存答案*/

il void pushup(int rt) //作用類似與線段樹

il void pushdown(int now)

}il int getson(int x) //getson判斷x是其父親的右兒子還是左兒子

il void rotate(int x) //旋轉操作,直接寫在乙個函式裡,可以稱為上旋

il void splay(int x, int i)

/*若x和y為相同偏向,則進行zig-zig或zag-zag操作*/

else /*否則進行zig-zag或zag-zig操作*/

/*注意rotate函式中已經包含了這四種操作情況了*/

} }}il int find(int x) //查詢x的位置 }}

il int build(int l, int r, int rt) //建樹過程和線段樹類似

il void print(int now) //輸出時中序遍歷,按左根右輸出

int main()

print(root);

for (int i = 1; i <= n; i++)printf("%d ", ans[i + 1]); //輸出時將前驅還原為原數

return 0;

}

poj 3580&bzoj 1895

#include #include #include #include #include using namespace std;

typedef long long ll;

const int maxn = 2e5 + 7;

const int inf = 1e9;

int n, m;

int ch[maxn][2]; //0做孩子, 1右孩子

int f[maxn]; //每個節點的父親

int sz[maxn]; //每個節點為根子樹的大小

int val[maxn]; //這個節點所表示的值

int cnt[maxn]; //這個節點所表示值的數量

int mi[maxn]; //這個節點子樹的最小值

int rev[maxn]; //反轉標記

int lazy[maxn]; //延遲標記

int root; // splay的根

int tot; //樹所有的節點數量

void swap(int &x, int &y)

int min(int x, int y)

void update_rev(int x) //更新反轉

void update_add(int x, int v)

void newnode(int rt, int v, int fa)

void delnode(int rt) //為了**空間,其實沒什麼太大的用處

void pushup(int x) //跟線段樹一樣,從下往上不斷更新

void pushdown(int x) //向下傳遞lazy 跟 rev

if (rev[x]) }

void build(int &rt, int l, int r, int fa) //rt是節點編號,節點的大小代表了兩個數字置的相對順序

void rotate(int x, int k) // k = 0左旋, k = 1右旋

void splay(int x, int goal)

} pushup(x);

if (goal == 0) root = x;

}//以x為根的子樹 的極值點 0 極小 1 極大

int extreme(int x, int k)

//以節點編號x為根的子樹 第k個數的節點編號

int kth(int x, int k)

//區間交換

void exchange(int l1, int r1, int l2, int r2)

//區間翻轉

void reversal(int l, int r)

//區間加

void add(int l, int r, int v)

//在第k個數後插入值為x的節點

void insert(int k, int x)

//刪除第k位置的數

void delete(int k)

// 獲取區間最大值

//int get_max(int l,int r)

////獲取區間最小值

int get_min(int l, int r)

void init(int n)

char s[12];

int main()

else if (s[0] == 'i')

else if (s[0] == 'm')

else if (s[0] == 'd')

else if (s[3] == 'e')

else

}return 0;

}

文藝平衡樹(splay模板)

題幹 splay模板,要求維護區間反轉。splay是一種碼量小於treap,但支援排名,前驅後繼等treap可求的東西,也支援區間反轉的平衡樹。但是有兩個壞處 1.splay常數遠遠大於treap以及stl中的set。2.沒有可持久化splay,但有可持久化treap。下面是 1.pushup以及p...

模板 文藝平衡樹(Splay)

這是一道經典的splay模板題 文藝平衡樹。輸入格式 第一行為n,m n表示初始序列有n個數,這個序列依次是 1,2,cdots n 1,n 1,2,n 1,n m表示翻轉操作次數 接下來m行每行兩個數 l,r l,r 資料保證 1 leq l leq r leq n1 l r n 輸出格式 輸出一...

文藝平衡樹 Splay

鏈結 splay板子題 結果還調了很久的題,這就是搞文化課的 顯然維護陣列下標,使得splay的中序遍歷始終為當前數列 值得注意 旋轉時始終要記得更新節點 注意更新root節點 每次寫都忘.jpg includeusing namespace std const int maxn 100000 10...