您需要寫一種資料結構,來維護乙個有序序列。
其中需要提供以下操作:翻轉乙個區間,例如原有序列是5 4 3 2 1,翻轉區間是[2,4],結果為5 2 3 4 1
a[5]=那麼存入文藝平衡樹之後,再中序遍歷的結果應該還是:。即下標從小到大,而不是裡面的值從小到大!這是與普通平衡樹的最大的不同!文藝平衡樹經過rotate旋轉之後,它的中序遍歷是不變的(即,下標從小到大)。但是讓這顆樹的一部分區間倒置之後。這個中序遍歷下標就不是遞增的了。
1.建樹
就像給線段樹建樹一樣,但是在原陣列的基礎上加乙個-inf,+inf。(比如原序列是1,2,3,4。你建樹的時候要給-inf,1,2,3,4,+inf建樹)
至於為什麼這樣做,就是為了可以給區間[ 1,n ]倒置
主函式:
int
main()
write
(root)
;//system("pause");
return0;
}
這個沒有輸入對應的n個數,而是用1,2,……n來代表,你也可以輸入
struct splay_tree
tr[n]
;void
pushup
(int x)
//更新節點資訊
void
pushdown
(int x)
//相當於線段樹操作的懶惰標記
中序遍歷輸出
void
write
(int now)
綠色的線就是輸出的過程,綠色的數字就是輸出順序
那麼最重要的區間翻轉操作,改怎麼找到翻轉區間呢(畢竟只有先找到了才能打上標記呀)
那麼實際上我們可以發現,在反轉區間[l~r]的時候,我們可以考慮利用splay的性質,將l-1翻轉至根節點,再將r+1翻轉至根節點的右兒子,類似這樣:
//將區間[l,r]翻轉
那麼至於旋轉操作的話和普通平衡樹是一樣的,這裡就不過多贅述了,只是在旋轉過程中不要忘了pushdown哦。
void
rotate
(int x)
完整**:
#include
using
namespace std;
const
int n=
1e5+
10,inf=
1e9+10;
struct splay_tree
tr[n]
;int a[n]
;int root,tot;
void
pushup
(int x)
void
pushdown
(int x)
}int
build_tree
(int fx,
int l,
int r)
void
rotate
(int x)
void
splay
(int x,
int s)
if(s==
0) root=x;
}int
kth(
int x)
else u=y;}}
void
turn
(int l,
int r)
//將區間[l,r]翻轉
void
write
(int now)
intmain()
write
(root)
;//system("pause");
return0;
}
除了區間翻轉,還可以實現
1.區間加
2.區間刪除
3.在第x個數後插入乙個數p
4.刪去第x個數(其實就是變相的區間刪除)
5.查詢區間最小值
6.查詢區間和
#include
using
namespace std;
const
int n=
1e5+
10,inf=
1e9+10;
struct splay_tree
tr[n]
;int a[n]
;int root,tot;
void
pushup
(int x)
void
pushdown
(int x)
if(x&&tr[x]
.add)
//區間加標記
}int
build_tree
(int fx,
int l,
int r)
void
rotate
(int x)
void
splay
(int x,
int s)
if(s==
0) root=x;
}int
kth(
int x)
else u=y;}}
//下面為各種操作
void
turn
(int l,
int r)
//將區間[l,r]翻轉
void
delete
(int l,
int r)
//區間刪除
void
insert
(int x,
int y)
//在第x個數之後插入數p
void
add(
int l,
int r,
int x)
//區間加
void
write
(int now)
intmain()
else
if(op==2)
//區間刪除操作
else
if(op==3)
//在第x個數後插入數p
else
if(op==4)
//區間加
}write
(root)
;//system("pause");
return0;
}
有些我也沒在題目裡交過,如果有錯,望告知。 文藝平衡樹
和splay差不多,就是維護區間,把siz值為l 1 1與r 1 1的兩個節點,將乙個旋轉到根,另乙個旋轉到根的右兒子上,則要修改的區間就是根的右孩子的左子樹,直接打標記即可。推薦 遠航之曲dalao writer hsz wjmzbmr tourist hzwer include include ...
文藝平衡樹
前置知識 普通平衡樹。實際上,平衡樹能做到的操作不只有插入刪除,查排名查值,前驅後繼這些。如果我們把平衡樹移到區間上,我們甚至能夠支援比線段樹更強的操作 區間翻轉。這就是文藝平衡樹這道題了。首先我們來明確一下區間樹的概念。顧名思義,區間樹就是用來維護區間的。具體地,我們規定平衡樹的中序遍歷得到的數列...
模板 文藝平衡樹
由於中序遍歷不會因為旋轉改變,平衡樹可以作為區間樹使用。翻轉用打標記的方法,splay x,y 代表把x接到以y為根的子樹下面。include include using namespace std const int maxn 100005 int n,m int val maxn siz max...