第一棵伸展树,各种调试模板……TVT

对于 1 n 这种查询我处理的不太好,之前序列前后没有添加冗余节点,一直Runtime Error。

后来加上冗余节点之后又出了别的状况,因为多了 0 和 n+1 这两个节点,并且每次截取翻转添加到序列最后,因此无法确定 n+1 这个节点在序列的哪个位置。

比如(括号中的为添加的冗余节点):

(0) 1 2 3 4 5 (6)

我把[3,4]截取翻转添加到序列尾部,会变成这样:

(0)1 2 5 (6)4 3

此时我如果再希望截取[3,4],期望的结果应该是:

1 2 3 4 5

而实际上会变成:

(0)1 2 4 3 (6) 5

我用了一种挺麻烦的方式解决的这个问题:

就是让伸展树在冗余节点n+1之前的位置再分裂一次,每次把截取的序列添加到节点n+1的前面,一直维持n+1在序列最末尾,这样就不会有干扰了。

 #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm> using namespace std; struct Node
{
Node *ch[];
int v, s;
int flip;
Node( int v ):v(v)
{
ch[] = ch[] = NULL;
s = ;
flip = ;
}
int cmp( int x ) const
{
int t = ( ch[] == NULL ) ? : ch[]->s;
if ( t >= x ) return ;
if ( t + == x ) return -;
return ;
}
void maintain()
{
s = ;
if ( ch[] != NULL ) s += ch[]->s;
if ( ch[] != NULL ) s += ch[]->s;
return;
}
void pushDown()
{
if ( flip )
{
flip = ;
swap( ch[], ch[] );
if ( ch[] != NULL ) ch[]->flip = !ch[]->flip;
if ( ch[] != NULL ) ch[]->flip = !ch[]->flip;
}
}
}; int n, m; void Rotate( Node* &o, int d ) //d=0 左旋 d=1 右旋
{
Node *k = o->ch[ d ^ ];
o->ch[ d ^ ] = k->ch[d];
k->ch[d] = o;
o = k;
o->ch[d]->maintain();
o->maintain();
return;
} void splay( Node* &o, int k )
{
o->pushDown();
int d = o->cmp(k);
if ( d == )
{
if ( o->ch[] != NULL )
k -= o->ch[]->s;
--k;
}
if ( d != - )
{
Node *p = o->ch[d];
p->pushDown();
int d2 = p->cmp(k);
int k2 = k;
if ( d2 == )
{
if ( p->ch[] != NULL )
k2 -= p->ch[]->s;
--k2;
}
if ( d2 != - )
{
splay( p->ch[d2], k2 );
if ( d == d2 ) Rotate( o, d ^ );
else Rotate( o->ch[d], d );
}
Rotate( o, d ^ );
}
return;
} Node *Merge( Node *left, Node *right )
{
splay( left, left->s );
left->ch[] = right;
left->maintain();
return left;
} void Split( Node *o, int k, Node* &left, Node* &right )
{
splay( o, k );
left = o;
right = o->ch[];
o->ch[] = NULL;
left->maintain();
return;
} void build( Node* &o, int l, int r )
{
int m = ( l + r ) >> ;
o = new Node(m);
if ( l < m ) build( o->ch[], l, m - );
if ( r > m ) build( o->ch[], m + , r );
o->maintain();
return;
} void DFS( Node *cur )
{
cur->pushDown();
if ( cur->ch[] ) DFS( cur->ch[] );
if ( cur->v && cur->v != n + ) printf( "%d\n", cur->v );
if ( cur->ch[] ) DFS( cur->ch[] );
return;
} void DeleteTree( Node *cur )
{
if ( cur->ch[] ) DeleteTree( cur->ch[] );
if ( cur->ch[] ) DeleteTree( cur->ch[] );
delete cur;
return;
} Node *root; int main()
{
while ( ~scanf( "%d%d", &n, &m ) )
{
root = NULL;
build( root, , n + ); //前后各加了一个冗余节点
while ( m-- )
{
int a, b;
scanf( "%d%d", &a, &b );
Node *left, *mid, *right, *o, *tmp; Split( root, a, left, o );
Split( o, b - a + , mid, right ); if ( right->s - > )
{
Split( right, right->s - , tmp, o );
mid->flip ^= ;
root = Merge( left, Merge( Merge( tmp, mid ), o ) );
}
else
{
mid->flip ^= ;
root = Merge( left, Merge( mid, right ) );
}
}
DFS( root );
DeleteTree( root );
}
return ;
}

UVa 11922 - Permutation Transformer 伸展树的更多相关文章

  1. UVA 11922 Permutation Transformer —— splay伸展树

    题意:根据m条指令改变排列1 2 3 4 … n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...

  2. UVA 11922 Permutation Transformer(平衡二叉树)

    Description Write a program to transform the permutation 1, 2, 3,..., n according to m instructions. ...

  3. UVA 11922 Permutation Transformer(Splay Tree)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 [思路] 伸展树+打标记. 用伸展树维护这个序列,使得能 ...

  4. UVA 11922 Permutation Transformer (Splay树)

    题意: 给一个序列,是从1~n共n个的自然数,接下来又m个区间,对于每个区间[a,b],从第a个到第b个从序列中分离出来,翻转后接到尾部.输出最后的序列. 思路: 这次添加了Split和Merge两个 ...

  5. uva 11922 - Permutation Transformer

    splay的题: 学习白书上和网上的代码敲的: #include <cstdio> #include <cstring> #include <cstdlib> #i ...

  6. UVA - 11922 Permutation Transformer (splay)

    题目链接 题意:你的任务是根据m条指令改变排列{!,2,3,...,n}.每条指令(a,b)表示取出第a~b个元素,翻转后添加到排列的尾部.输出最终序列. 解法:splay对区间分裂合并翻转,模板题. ...

  7. uva 11922 Permutation Transforme/splay tree

    原题链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 伸展树的区间翻转剪切... 如下: #include< ...

  8. uva 12003 Array Transformer (线段树套平衡树)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  9. UVA 11525 Permutation ——(线段树,脑筋急转弯)

    只要注意到对于譬如:S1*(k-1)! 因为后面k-1个数字的全排列个数刚好是(k-1)!,那么第一个数字就是没有取过的数字的第(S1+1)个即可.取走这个数字以后这个数字就不能再用了,依次类推即可得 ...

随机推荐

  1. java实现合并两个已经排序的列表

    相对于C++来说,Java的最大特点之一就是没有令人困惑的指针,但是我们不可否认,在某些特定的情境下,指针确实算的上一把利刃.虽然Java中没有明确定义出指针,但是由于类的思想,我们可以使用class ...

  2. input 标签的监听事件总结

    最近在写一个手机端提交表单的项目,里面用了不少input标签,因为项目不太忙,所以,想做的完美点,但是遇到了一些问题,比如:页面中的必填项如果有至少一项为空,提交按钮就是不能提交的状态,所以需要对所有 ...

  3. c++类中的静态成员

    静态成员和非静态成员的区别: 类静态成员用static修饰,类的静态成员属于类本身,而不属于类的某个具体对象,静态成员被类的所有对象共享,因此某个对象对静态成员(数据成员)的修改对其对象是可见的.而类 ...

  4. 分析 "ADO" "ADODB" "ADODC" 之间的区别与联系

    在敲学生信息管理系统的时候,通过查阅了解了一些关于 ADO / ADODB / ADODC / 的简单描述,想想将他们对 比着总结一下更容易理解记忆.尽管都是一些浅显的东西,不过对像我这样的菜鸟们还是 ...

  5. android开发,assets下面的资源文件不会变化/改动

    我再调试asserts下面的资源文件,发现我改动assets下面的文件内容,在真机上测试的时候还是最原先的内容,没有变,后来,卸载,重装就ok了. 原因: assets下面的资源文件,若覆盖重装,则里 ...

  6. 无法将 flash.display::Sprite@156b7b1 转换为 mx.core.IUIComponent

    无法将 flash.display::Sprite@156b7b1 转换为 mx.core.IUIComponent 在Flex Application里,是不能直接用addChild添加Sprite ...

  7. 管理Java垃圾回收的五个建议

    [编者按]本文作者是Niv Steingarten,是Takipi 的联合创始人,热衷于编写优雅简洁的代码.作者通过对垃圾收集器的介绍和梳理,在管理垃圾回收方面提出了五个建议,降低收集器开销,帮助大家 ...

  8. SPOJ LGLOVE 7488 LCM GCD Love (区间更新,预处理出LCM(1,2,...,n))

    题目连接:http://www.spoj.com/problems/LGLOVE/ 题意:给出n个初始序列a[1],a[2],...,a[n],b[i]表示LCM(1,2,3,...,a[i]),即1 ...

  9. POJ 1459 Power Network(网络最大流,dinic算法模板题)

    题意:给出n,np,nc,m,n为节点数,np为发电站数,nc为用电厂数,m为边的个数.      接下来给出m个数据(u,v)z,表示w(u,v)允许传输的最大电力为z:np个数据(u)z,表示发电 ...

  10. 转一篇:文档笔记之Django QuerySet

    这个放着,说不定以后作一些更深入的查询时,用得着的. http://www.rapospectre.com/blog/7/ 今天刚刚答完辩体完检就跑来更新博客了!!! 先补上第一篇: 一般情况下,我们 ...