當(dāng)前位置:
首頁 >
P3391 【模板】文艺平衡树(Splay)
發(fā)布時(shí)間:2025/6/16
58
豆豆
生活随笔
收集整理的這篇文章主要介紹了
P3391 【模板】文艺平衡树(Splay)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Splay
#include<cstdio> #include<algorithm> #include<iostream> using namespace std; struct node *nil;//防止真的訪問了NULL導(dǎo)致re(從零開始的編碼生活) struct node {int val;//節(jié)點(diǎn)值int size;//以他為根的節(jié)點(diǎn)的子樹節(jié)點(diǎn)個(gè)數(shù)(包括他自己)int flag;//懶標(biāo)記node *ch[2];//左右兒子void sum()//重新計(jì)算size{size=1+ch[0]->size+ch[1]->size;//因?yàn)檫@里我們定義了不會(huì)re的無意義空地址。所以就不用判斷}int cmp(int kth)//比較該往那顆子樹上走{int s=ch[0]->size;if(kth==s+1)//就是當(dāng)前根return -1;return (kth <= s ? 0 : 1);} }*root; int n,m; void init()//初始化 {nil=new node;nil->flag=0;nil->size=0;nil->val=0;nil->ch[0]=nil->ch[1]=nil;root=nil; } node *New()//申請(qǐng)內(nèi)存并初始化 {node *res=new node;res->size=1;res->flag=0;res->ch[0]=res->ch[1]=nil;return res; } void rotato(node* &now,int base)//旋轉(zhuǎn)函數(shù)。應(yīng)為這里是引用指針。所以直接指向就可以了。不用顧忌其他東西辣( ̄▽ ̄)~* {node *k=now->ch[base^1];//利用異或進(jìn)行取反now->ch[base^1]=k->ch[base];k->ch[base]=now;now->sum();//先計(jì)算被旋轉(zhuǎn)下去的根,再計(jì)算新的根k->sum();now=k; } void build(node* &now,int l,int r)//建樹,一定要引用。l為左邊界。 {if(l>r)return ;int mid=(l+r)>>1;if(now==nil)//如果為空就動(dòng)態(tài)申請(qǐng),當(dāng)然也可以動(dòng)態(tài)刪除{now=New();now->val=mid;}build(now->ch[0],l,mid-1);//左右遞歸的建樹build(now->ch[1],mid+1,r);now->sum();return ; } void push_down(node* &now)//下放lazy tag {if(now!=nil&&now->flag){swap(now->ch[0],now->ch[1]);now->ch[0]->flag^=1;now->ch[1]->flag^=1;now->flag=0;}return ; } void visit(node* &now)//中序便利 {if(now==nil)return ;push_down(now);visit(now->ch[0]);if(now->val!=0&&now->val!=n+1)printf("%d ",now->val);visit(now->ch[1]); } void splaykth(node* &now,int kth)//將以now為根的樹中把第kth小的旋轉(zhuǎn)到根上 {push_down(now);int d=now->cmp(kth);if(d!=-1){push_down(now->ch[d]);if(d==1)kth-=now->ch[0]->size+1;//換根要重新計(jì)算kth,下同int d2=now->ch[d]->cmp(kth);if(d2!=-1){if(d2==1)kth-=now->ch[d]->ch[0]->size+1;splaykth(now->ch[d]->ch[d2],kth);if(d==d2)rotato(now,d2^1),rotato(now,d^1);//一字型elserotato(now->ch[d],d2^1),rotato(now,d^1);//之字形}elserotato(now,d^1);//單旋} }//其實(shí)這里應(yīng)該要判空的,以防止非法情況出現(xiàn)。不過根據(jù)這個(gè)題。我們調(diào)用的時(shí)候沒有非法情況 void Reverse(int l,int r)//翻轉(zhuǎn),這里因?yàn)橛锌赡苌婕暗綄?~n都翻轉(zhuǎn)一遍。所以我們可以建兩個(gè)哨兵節(jié)點(diǎn),位置在0,n+1上。 { //將l~r翻轉(zhuǎn)//l,r為第l個(gè)數(shù)到第r個(gè)數(shù)(1~n中)splaykth(root,l);//把l-1翻上來splaykth(root->ch[1],r+1-root->ch[0]->size);//把r+1翻到右子樹根的位置上。這樣根節(jié)點(diǎn)右兒子的左子樹上就是l~r。root->ch[1]->ch[0]->flag^=1;//打上懶標(biāo)記return ; } int main() {init();scanf("%d%d",&n,&m);build(root,0,n+1);int a,b;for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);Reverse(a,b);}/*splaykth(root,7);cout<<root->val;*/visit(root);//中序遍歷一波 }轉(zhuǎn)載于:https://www.cnblogs.com/Lance1ot/p/9047440.html
總結(jié)
以上是生活随笔為你收集整理的P3391 【模板】文艺平衡树(Splay)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot的注解:@Sprin
- 下一篇: Microsoft 365及应用开发的未