Splay
阿新 • • 發佈:2017-07-30
pri pushd 元素 new else merge tdi size void
1 // UVa11922 Permutation Transformer 2 // Rujia Liu 3 #include<cstdio> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 8 struct Node { 9 Node *ch[2]; 10 int s; 11 int flip; 12 int v; 13 int cmp(int k) const { 14 int d = k - ch[0]->s;15 if(d == 1) return -1; 16 return d <= 0 ? 0 : 1; 17 } 18 void maintain() { 19 s = ch[0]->s + ch[1]->s + 1; 20 } 21 void pushdown() { 22 if(flip) { 23 flip = 0; 24 swap(ch[0], ch[1]); 25 ch[0]->flip = !ch[0]->flip; 26 ch[1]->flip = !ch[1]->flip; 27 } 28 } 29 }; 30 31 Node *null = new Node(); 32 33 void rotate(Node* &o, int d) { 34 Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o; 35 o->maintain(); k->maintain(); o = k; 36 } 37 38 void splay(Node* &o, int k) { 39 o->pushdown();40 int d = o->cmp(k); 41 if(d == 1) k -= o->ch[0]->s + 1; 42 if(d != -1) { 43 Node* p = o->ch[d]; 44 p->pushdown(); 45 int d2 = p->cmp(k); 46 int k2 = (d2 == 0 ? k : k - p->ch[0]->s - 1); 47 if(d2 != -1) { 48 splay(p->ch[d2], k2); 49 if(d == d2) rotate(o, d^1); else rotate(o->ch[d], d); 50 } 51 rotate(o, d^1); 52 } 53 } 54 55 // 合並left和right。假定left的所有元素比right小。註意right可以是null,但left不可以 56 Node* merge(Node* left, Node* right) { 57 splay(left, left->s); 58 left->ch[1] = right; 59 left->maintain(); 60 return left; 61 } 62 63 // 把o的前k小結點放在left裏,其他的放在right裏。1<=k<=o->s。當k=o->s時,right=null 64 void split(Node* o, int k, Node* &left, Node* &right) { 65 splay(o, k); 66 left = o; 67 right = o->ch[1]; 68 o->ch[1] = null; 69 left->maintain(); 70 } 71 72 const int maxn = 100000 + 10; 73 struct SplaySequence { 74 int n; 75 Node seq[maxn]; 76 Node *root; 77 78 Node* build(int sz) { 79 if(!sz) return null; 80 Node* L = build(sz/2); 81 Node* o = &seq[++n]; 82 o->v = n; // 節點編號 83 o->ch[0] = L; 84 o->ch[1] = build(sz - sz/2 - 1); 85 o->flip = o->s = 0; 86 o->maintain(); 87 return o; 88 } 89 90 void init(int sz) { 91 n = 0; 92 null->s = 0; 93 root = build(sz); 94 } 95 }; 96 97 vector<int> ans; 98 void print(Node* o) { 99 if(o != null) { 100 o->pushdown(); 101 print(o->ch[0]); 102 ans.push_back(o->v); 103 print(o->ch[1]); 104 } 105 } 106 107 void debug(Node* o) { 108 if(o != null) { 109 o->pushdown(); 110 debug(o->ch[0]); 111 printf("%d ", o->v-1); 112 debug(o->ch[1]); 113 } 114 } 115 116 SplaySequence ss; 117 int main() 118 { 119 int n, m; 120 scanf("%d%d", &n, &m); 121 ss.init(n+1); // 最前面有一個虛擬結點 122 123 while (m--) { 124 int a, b; 125 scanf("%d%d", &a, &b); 126 Node *left, *mid, *right, *o; 127 split(ss.root, a, left, o); // 如果沒有虛擬結點,a將改成a-1,違反split的限制 128 split(o, b-a+1, mid, right); 129 mid->flip ^= 1; 130 ss.root = merge(merge(left, right), mid); 131 } 132 133 print(ss.root); 134 for(int i = 1; i < ans.size(); i++) 135 printf("%d\n", ans[i]-1); // 節點編號減1才是本題的元素值 136 137 return 0; 138 }
Splay