日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P3391 【模板】文艺平衡树(Splay)

發布時間:2025/6/16 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P3391 【模板】文艺平衡树(Splay) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Splay

#include<cstdio> #include<algorithm> #include<iostream> using namespace std; struct node *nil;//防止真的訪問了NULL導致re(從零開始的編碼生活) struct node {int val;//節點值int size;//以他為根的節點的子樹節點個數(包括他自己)int flag;//懶標記node *ch[2];//左右兒子void sum()//重新計算size{size=1+ch[0]->size+ch[1]->size;//因為這里我們定義了不會re的無意義空地址。所以就不用判斷}int cmp(int kth)//比較該往那顆子樹上走{int s=ch[0]->size;if(kth==s+1)//就是當前根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()//申請內存并初始化 {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)//旋轉函數。應為這里是引用指針。所以直接指向就可以了。不用顧忌其他東西辣( ̄▽ ̄)~* {node *k=now->ch[base^1];//利用異或進行取反now->ch[base^1]=k->ch[base];k->ch[base]=now;now->sum();//先計算被旋轉下去的根,再計算新的根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)//如果為空就動態申請,當然也可以動態刪除{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小的旋轉到根上 {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;//換根要重新計算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);//單旋} }//其實這里應該要判空的,以防止非法情況出現。不過根據這個題。我們調用的時候沒有非法情況 void Reverse(int l,int r)//翻轉,這里因為有可能涉及到將1~n都翻轉一遍。所以我們可以建兩個哨兵節點,位置在0,n+1上。 { //將l~r翻轉//l,r為第l個數到第r個數(1~n中)splaykth(root,l);//把l-1翻上來splaykth(root->ch[1],r+1-root->ch[0]->size);//把r+1翻到右子樹根的位置上。這樣根節點右兒子的左子樹上就是l~r。root->ch[1]->ch[0]->flag^=1;//打上懶標記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);//中序遍歷一波 }

轉載于:https://www.cnblogs.com/Lance1ot/p/9047440.html

總結

以上是生活随笔為你收集整理的P3391 【模板】文艺平衡树(Splay)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。