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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

UVA_11922 Permutation Transformer 【splay树】

發布時間:2025/7/25 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UVA_11922 Permutation Transformer 【splay树】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、題目

UVA11922

二、分析

為什么會有伸展樹?

伸展樹與AVL的區別除了保持平衡的方式不同外,最重要的是在每次查找點時,讓該點旋轉到根結點,這里可以結合計算機里的局部性原理思考。

伸展樹有什么優勢?

有了伸展樹,我們可以根據每次到根節點的值,根據二叉搜索樹的性質,可以將整棵樹劃分成兩個部分,左子樹的值都比根結點值大,右子樹的值都比根結點小。

該題除了伸展樹還用到了什么?

該題還需要旋轉,所以,需要像線段樹的lazy標記一樣標記是否需要旋轉。

有什么需要注意的地方?

一定注意寫法的不同,構建樹的范圍不同,如果沒有定于null數組,則需要將建樹范圍從$[1,n]$擴為$[0,n]$,因為空指針的sum(表示以該結點為根的樹的大小)是不清楚的。

三、AC代碼

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 struct Node 8 { 9 Node *ch[2]; 10 int sum, val; 11 int flip; 12 Node(int v = 0) 13 { 14 val = v; 15 sum = 1; 16 flip = 0; 17 ch[0] = ch[1] = NULL; 18 } 19 int cmp(int x) 20 { 21 int d = x - (ch[0] == NULL ? 0 : ch[0]->sum); 22 if(d == 1) return -1; 23 else return d <= 0 ? 0 : 1; 24 } 25 void maintain() 26 { 27 sum = 1; 28 if(ch[0] != NULL) sum += ch[0]->sum; 29 if(ch[1] != NULL) sum += ch[1]->sum; 30 } 31 void pushdown() 32 { 33 if(flip) 34 { 35 flip = 0; 36 swap(ch[0], ch[1]); //** 37 if(ch[0] != NULL) 38 ch[0]->flip = !ch[0]->flip; 39 if(ch[1] != NULL) 40 ch[1]->flip = !ch[1]->flip; 41 } 42 } 43 }; 44 45 void build(Node* &o, int l, int r) 46 { 47 if(l > r) 48 return; 49 int mid = (l + r) >> 1; 50 o = new Node(mid); 51 build(o->ch[0], l, mid - 1); 52 build(o->ch[1], mid + 1, r); 53 o->maintain(); 54 } 55 56 void rotate(Node* &o, int d) 57 { 58 Node *k = o->ch[d^1]; 59 o->ch[d^1] = k->ch[d]; 60 k->ch[d] = o; 61 o->maintain(); 62 k->maintain(); 63 o = k; 64 } 65 66 67 void splay(Node* &o, int k) 68 { 69 o->pushdown(); 70 int d = o->cmp(k); 71 if(d == 1) 72 k -= (o->ch[0] == NULL ? 0 : o->ch[0]->sum) + 1; 73 //當前結點不是第k個,則需要往上伸展 74 if(d != -1) 75 { 76 Node *p = o->ch[d]; 77 p->pushdown(); 78 79 int d2 = p->cmp(k); 80 int k2 = (d2 == 0 ? k : k - (p->ch[0] == NULL ? 0 :p->ch[0]->sum) - 1); 81 if(d2 != -1) 82 { 83 splay(p->ch[d2], k2); 84 //x,x的父節點,x祖父結點三點共線 85 if(d == d2) rotate(o, d^1); 86 //不共線 87 else rotate(o->ch[d], d); 88 } 89 rotate(o, d^1); 90 } 91 } 92 93 94 void print(Node* &o) //一定要傳引用 95 { 96 o->pushdown(); 97 if(o->ch[0] != NULL) print(o->ch[0]); 98 if(o->val) 99 printf("%d\n", o->val); 100 if(o->ch[1] != NULL) print(o->ch[1]); 101 102 delete o; 103 o = NULL; 104 } 105 106 Node* merge(Node* left, Node* right) 107 { 108 //left不能為NULL 109 //因為初始化了sum為1,對于空指針的sum,不清楚大小 110 //如何避免:建樹從0開始,即保證sum>0 111 splay(left, left->sum); 112 left->ch[1] = right; 113 left->maintain(); 114 return left; 115 } 116 117 118 void split(Node *o, int k, Node* &left, Node* &right) 119 { 120 splay(o, k); 121 left = o; 122 right = o->ch[1]; 123 o->ch[1] = NULL; 124 left->maintain(); 125 } 126 127 128 int main() 129 { 130 //freopen("input.txt", "r", stdin); 131 //freopen("out.txt", "w", stdout); 132 int N, M, a, b; 133 while(scanf("%d %d", &N, &M)==2) 134 { 135 Node *root = NULL; 136 Node *left, *mid, *right, *o; 137 //上述模板注意不能用空指針 138 //必須從0開始,不然會RE 139 build(root, 0, N); 140 141 for(int i = 0; i < M; i++) 142 { 143 scanf("%d %d", &a, &b); 144 //樹里面有0所以是a 145 split(root, a, left, o); 146 split(o, b - a + 1, mid, right); 147 mid->flip ^= 1; 148 root = merge(merge(left, right), mid); 149 } 150 print(root); 151 } 152 return 0; 153 }

?

轉載于:https://www.cnblogs.com/dybala21/p/10725777.html

總結

以上是生活随笔為你收集整理的UVA_11922 Permutation Transformer 【splay树】的全部內容,希望文章能夠幫你解決所遇到的問題。

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