山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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  阅读(309)  评论(0编辑  收藏  举报