UVA 11922 Permutation Transformer(Splay Tree)
题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902
【思路】
伸展树+打标记。
用伸展树维护这个序列,使得能够提供快速的分裂与合并O(logn),利用打标记的方法处理区间翻转的问题。
需要注意的有:
1)在splay与print中都需要合适地调用pushdown下传标记。
2)Merge操作应该满足left中所有元素都比right中的元素小,这里的大小定义为序列位置的大小而不是键值v的大小。
3)因为merge操作不能使left为空所以需要添加一个虚拟节点。
【代码】
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<iostream> 5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 6 using namespace std; 7 8 const int maxn = 100000+10; 9 10 struct Node{ 11 Node* ch[2]; 12 int v,s,flip; 13 int cmp(int k) { 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^=1; 26 ch[1]->flip^=1; 27 } 28 } 29 }; 30 Node* null=new Node(); 31 32 void rotate(Node* &o,int d) { 33 Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; 34 o->maintain(),k->maintain(); o=k; 35 } 36 void splay(Node* &o,int k) { 37 o->pushdown(); 38 int d=o->cmp(k); 39 if(d==1) k-=o->ch[0]->s+1; 40 if(d!=-1) { 41 Node* p=o->ch[d]; 42 p->pushdown(); 43 int d2=p->cmp(k); 44 int k2=d2==0? k:k-p->ch[0]->s-1; 45 if(d2!=-1) { 46 splay(p->ch[d2],k2); 47 if(d==d2) rotate(o,d^1); else rotate(o->ch[d],d); 48 } 49 rotate(o,d^1); 50 } 51 } 52 Node* merge(Node* left,Node* right) { 53 splay(left,left->s); 54 left->ch[1]=right,left->maintain(); 55 return left; 56 } 57 void split(Node* o,int k,Node* &left,Node* &right) { 58 splay(o,k); 59 left=o,right=left->ch[1],left->ch[1]=null; 60 left->maintain(); 61 } 62 63 struct SplaySequence { 64 int n; 65 Node seq[maxn]; 66 Node* root; 67 68 Node* build(int sz) { 69 if(!sz) return null; 70 Node* l=build(sz/2); 71 Node* o=&seq[++n]; 72 o->v=n; 73 o->ch[0]=l; 74 o->ch[1]=build(sz-sz/2-1); 75 o->flip=o->s=0; 76 o->maintain(); 77 return o; 78 } 79 void init(int sz) { 80 n=null->s=0; 81 root=build(sz); 82 } 83 }spaly; 84 85 vector<int> ans; 86 void print(Node* o) { 87 if(o!=null) { 88 o->pushdown(); 89 print(o->ch[0]); 90 ans.push_back(o->v); 91 print(o->ch[1]); 92 } 93 } 94 95 int n,m; 96 int main() { 97 scanf("%d%d",&n,&m); 98 spaly.init(n+1); //在开始添加虚拟结点 99 int l,r; 100 Node *left,*right,*mid; 101 while(m--) { 102 scanf("%d%d",&l,&r); 103 split(spaly.root,l,left,right); 104 split(right,r-l+1,mid,right); 105 mid->flip^=1; 106 spaly.root = merge(merge(left,right),mid); 107 } 108 print(spaly.root); 109 for(int i=1;i<ans.size();i++) printf("%d\n",ans[i]-1); 110 return 0; 111 }
posted on 2015-12-03 14:49 hahalidaxin 阅读(311) 评论(0) 编辑 收藏 举报