【學習筆記】兩種非旋轉平衡樹在OI中的應用
【學習筆記】兩種非旋轉平衡樹在OI中的應用
前言
掛完之後打算把資料結構啃完(不包括 等神仙資料結構),於是就開始學習非旋轉的平衡樹了。然後發現自己被旋轉平衡樹坑了好久。。非旋轉的程式碼各種吊打旋轉平衡樹。。。。廢話不多說,今天主要討論的兩種非旋轉平衡樹分別是fhqTreap和替罪羊樹。
fhqTreap
非旋轉
,範浩強
。
眾所周知,
相當於是
而
的複雜度保證基於期望意義下樹的深度不超過
,而Treap採用旋轉是為了滿足堆的性質。
也就是說,
的旋轉操作和複雜度並不直接掛鉤,我們拋棄以前的旋轉做法,考慮如何插入一個節點
。
一種神奇的思路是,把一棵樹劈開,分成兩棵樹
,這兩棵樹中
。把一個節點看成一棵樹,把這三棵樹合併起來。
這就是FHQ著名的兩個操作
和
Split
假設當前節點為 ,插入節點的權值是 ,分兩種情況。
- ,此時當前節點以及整個左子樹都要放 中,之後如果再有節點放入左子樹,一定在當前節點的右邊。
- ,此時當前節點以及整個右子樹都要放 中,之後如果再有節點放入右子樹,一定在當前節點的左邊。
基於這個思路,採用引用的方式可以得到如下程式碼。
void Split(int u, int &a, int &b, int x) {
if(!u) return void(a = b = 0);
if(val[u] <= x)
a = u, Split(rs[u], rs[a], b, x);
else
b = u, Split(ls[u], a, ls[b], x);
Up(u);
}
核心操作1結束了。
Merge
類似左偏樹的合併,不過採用啟發式合併,因為 是一個堆,而 的過程保證了 的順序,所以合併的時候比較一下鍵值大小即可。
int Merge(int u, int v) {
if(!u || !v) return u | v;
if(key[u] < key[v]) return rs[u] = Merge(rs[u], v), Up(u), u;
return ls[v] = Merge(u, ls[v]), Up(v), v;
}
剩下的
插入的時候劈成兩棵樹合併即可。
void Ins(int x) {
int a = 0, b = 0; Get(x);
Split(rt, a, b, x);
a = Merge(a, nw);
rt = Merge(a, b);
}
刪除的時候劈成三棵樹刪除即可。
void Del(int x) {
int a = 0, b = 0, c = 0;
Split(rt, a, b, x);
Split(a, a, c, x - 1);
st[++tp] = c;
c = Merge(ls[c], rs[c]);
a = Merge(a, c);
rt = Merge(a, b);
}
查詢第 大就是在平衡樹上二分。
int Kth(int p, int k) {
for(;p;) {
if(sz[ls[p]] + 1 == k) return val[p];
sz[ls[p]] < k ? k -= sz[ls[p]] + 1, p = rs[p] : p = ls[p];
}
}
查詢排名,前驅和後繼就是劈開之後找第 大或者第 大
void Rk(int x) {
int a = 0, b = 0;
Split(rt, a, b, x - 1);
printf("%d\n", sz[a] + 1);
rt = Merge(a, b);
}
void Pre(int x) {
int a = 0, b = 0;
Split(rt, a, b, x - 1);
printf("%d\n", Kth(a, sz[a]));
rt = Merge(a, b);
}
void Nxt(int x) {
int a = 0, b = 0;
Split(rt, a, b, x);
printf("%d\n", Kth(b, 1));
rt = Merge(a, b);
}
都是平衡樹的正常操作,非旋轉 直觀容易理解,掌握了 和 之後可以快速提取出需要的樹,然後就是按照題意模擬即可。
總程式碼
#include<bits/stdc++.h>
const int N = 1e5 + 10;
int ri() {
char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int sz[N], ls[N], rs[N], val[N], key[N], st[N], tp, tot, rt = 1, nw, se = 233;
int Rand() {return se = 1LL * se * 998244353 & 0x7fffffff;}
void Get(int k) {
nw = tp ? st[tp--] : ++tot;
sz[nw] = 1; val[nw] = k; key[nw] = Rand();
ls[nw] = rs[nw] = 0;
}
void Up(int u) {sz[u] = sz[ls[u]] + sz[rs[u]] + 1;}
void Split(int u, int &a, int &b, int x) {
if(!u) return void(a = b = 0);
if(val[u] <= x)
a = u, Split(rs[u], rs[a], b, x);
else
b = u, Split(ls[u], a, ls[b], x);
Up(u);
}
int Merge(int u, int v) {
if(!u || !v) return u | v;
if(key[u] < key[v]) return rs[u] = Merge(rs[u], v), Up(u), u;
return ls[v] = Merge(u, ls[v]), Up(v), v;
}
int Kth(int p, int k) {
for(;p;) {
if(sz[ls[p]] + 1 == k) return val[p];
sz[ls[p]] < k ? k -= sz[ls[p]] + 1, p = rs[p] : p = ls[p];
}
}
void Rk(int x) {
int a = 0, b = 0;
Split(rt, a, b, x - 1);
printf("%d\n", sz[a] + 1);
rt = Merge(a, b);
}
void Pre(int x) {
int a = 0, b = 0;
Split(rt, a, b, x
相關推薦
【學習筆記】兩種非旋轉平衡樹在OI中的應用
【學習筆記】兩種非旋轉平衡樹在OI中的應用
前言
N
O
I
【學習筆記】資料庫優化之索引(聚簇索引&非聚簇索引)
索引:對資料庫表中一列或多列的值進行排序的一種結構,通過索引可快速訪問資料庫表中的特定資訊,即通過索引對資料列的值進行結構化排序。
其中,索引包含聚簇索引和非聚簇索引
聚簇索引的順序就是資料的物理儲存順序
非聚簇索引的索引順序與資料物理排列順序無關
所以一個表
【學習筆記】關於DOM4J:使用DOM4J解析XML文檔
文本 class 中產 獲取 ber exce int() logs hone 一、概述
DOM4J是一個易用的、開源的庫,用於XML、XPath和XSLT中。采用了Java集合框架並完全支持DOM、SAX、和JAXP。
DOM4J最大的特色是使用大量的接口,主要接口都在o
【學習筆記】Java中生成對象的5中方法
目標 獲得 cti com pre lan except 我們 highlight 概述:本文介紹以下java五種創建對象的方式:
1.用new語句創建對象,這是最常用的創建對象的方式。
2.使用Class類的newInstance方法
3.運用反射手段,調用java.la
【學習筆記】SIFT尺度不變特征 (配合UCF-CRCV課程視頻)
rri cnblogs -o mask 畫出 blocks http ucf 產生 SIFT尺度不變特征
D. Lowe. Distinctive image features from scale-invariant key points, IJCV 2004
-Lect
【學習筆記】String進階:StringBuffer類(線程安全)和StringBuilder類
n) static this util double 字符串 對象 ice 單線程 一、除了使用String類存儲字符串之外,還可以使用StringBuffer類存儲字符串。而且它是比String類更高效的存儲字符串的一種引用數據類型。
優點:
對字符串進行連接操作時,
【學習筆記】使用SQLyog連接MySQL數據庫
comm 丟失 school turn 復合主鍵 price not email pre 一、使用SQLyog創建數據庫用來管理學生信息
1 #創建數據庫student
2 DROP DATABASE IF EXISTS Myschool;
3 CREAT
【學習筆記】2017年7月18日MySQL測試:模擬QQ數據庫
關系 ref sts one database 等級 weight insert phone 模擬測試:
QQ數據庫管理
一、創建數據庫並添加關系和測試數據
1 ##創建QQ數據庫,完成簡單的測試
2
3 #創建數據庫
4 DROP DATABASE IF EX
【學習筆記】C# 構造和析構
成員 int 學習 pri [] func 釋放內存 ring 銷毀
構造方法
構造方法是一個特殊的方法,負責初始化對象
構造方法名必須和類名一致
構造方法沒有返回值,但可以有參數,能夠重載
構造方法可以不寫,系統會自動為類添加一個無參的默認構造
如果將構造方法設置為P
【學習筆記】C# 靜態類
實例化 namespace [] line str 過程 ole test 數據
靜態修飾符
用static修飾的成員是靜態成員
靜態成員只能由類來調用
用static修飾的類是靜態類
靜態類不能實例化,只能包含靜態成員和const常量
在內存中一共有五個區域
1
【學習筆記】C# 接口
apple [] oat 訪問 names 使用 foo pub 修飾
使用interface關鍵字定義接口
接口定義一組成員但不直接實現它們
實現接口
實現接口的任何類都必須實現其所有的成員方法
接口不能直接實例化
接口可以包含方法和屬性聲明,不能包含字段
接口中所有
【學習筆記】C# ArrayList
tde 獲取 style demo key ren mov cnblogs content
集合
集合是種容器,在程序中,使用集體管理相關對象組
集合分為非泛型集合和泛型集合
非泛型集合
使用非泛型集合需要引入命名空間System.Collections
Arra
【學習筆記】C# 字典
鍵值對 保存 包含 ear 是否 nod 對象 命名空間 不包含
字典
Dictionary是存儲鍵和值的集合
Dictionary是無序的,鍵Key是唯一的
使用時,首先要引入泛型集合命名空間 using System.Collections.Generic;
【學習筆記】python爬取百度真實url
python 今天跑個腳本需要一堆測試的url,,,挨個找復制粘貼肯定不是程序員的風格,so,還是寫個腳本吧。 環境:python2.7 編輯器:sublime text 3 一、分析一下 首先非常感謝百度大佬的url分類非常整齊,都在一個
【學習筆記】WebDriver操作第三方控件
webdriver 第三方控件 本文是風落幾番(任健勇)老師的課程《從零學習selenium2(WebDriver)自動化測試系列視頻課程》Lesson3-4第三方控件類操作的學習筆記第三方控件的操作,不同控件的操作方法一、上傳控件1.標準控件經過包裝:在標準的上傳控件input type=file之
【學習筆記】盧卡斯定理
namespace style pan set thml color 怎麽辦 alt fontsize 洛谷 P3807 【模板】盧卡斯定理
題目背景
這是一道模板題。
題目描述
給定n,m,p(1\le n,m,p\le 10^51≤n,m,p≤10?5??)
求 C_{
【學習筆記】計算機網絡-利用TELNET進行SMTP的郵件發送
alt tle smtp 用戶 sdn 編碼 out mark watermark 在命令行輸入telnet smtp.163.com 25 然後依次輸入內容 用戶名不包括@和後面的部分,用戶名和密碼均需base64編碼 成功收到郵件: 【學習筆記】計算機網絡-利用TEL
【學習筆記】python 進階特性
可能 pytho red nbsp python blog 有一個 自省 blue __slots__魔法
在Python中,每個類都有實例屬性。默認情況下Python用一個字典來保存一個對象的實例屬性。這非常有用,因為它允許我們在運行時去設置任意的新屬性。
然而,對於有
【學習筆記】初識FreeMarker簡單使用
als 大小 宋體 屬性 list mage equal port template 楔子:
之前在和同事討論,同事說“jsp技術太古老了,有幾種頁面技術代替,比如FreeMarker、Velocity、thymeleaf,jsp快廢棄了……”雲雲。我這一聽有點心虛…
【學習筆記】FreeMarker 之於Servlet與Stuts2的應用
patch warnings ftl 4.0 type shm .html enter src FreeMarker應用在Servlet(0配置web.xml形式):
準備環境:
tomcat7、eclipse最新版、jdk1.8、freemarker v2.3.20.ja