第一棵伸展树,各种调试模板……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大神?

    一.基础篇 1.1 JVM 1.1.1. Java内存模型,Java内存管理,Java堆和栈,垃圾回收 http://www.jcp.org/en/jsr/detail?id=133http://if ...

  2. .net 科学类型相关问题

    Q:如果我要把使用科学记数法表示的string转换为int又该如何呢? A:你可以通过把NumberStyles.AllowDecimalPoint | NumberStyles.AllowExpon ...

  3. Careercup - Google面试题 - 5732809947742208

    2014-05-03 22:10 题目链接 原题: Given a dictionary, and a list of letters ( or consider as a string), find ...

  4. Android使用XML做动画UI

    在Android应用程序,使用动画效果,能带给用户更好的感觉.做动画可以通过XML或Android代码.本教程中,介绍使用XML来做动画.在这里,介绍基本的动画,如淡入,淡出,旋转等. 效果: htt ...

  5. 深入浅出C++引用(Reference)类型

    要点1:为反复使用的.冗长的变量名称定义一个简短的.易用的别名,从而简化了代码.通常,冗长的变量名称源于多层嵌套对象,例如类中定义嵌套类,类中定义其它类对象. //------ 未使用引用的程序片段, ...

  6. shell find and rm

    按时间删除命令: 删除当前目录下30天以前的所有文件: find . -type f -ctime + -exec rm -fr {} \; 删除当前目录下30天以前的所有目录: find . -ty ...

  7. Codeforces Round #348 (VK Cup 2016 Round 2, Div. 2 Edition) D. Little Artem and Dance

    题目链接: http://codeforces.com/contest/669/problem/D 题意: 给你一个初始序列:1,2,3,...,n. 现在有两种操作: 1.循环左移,循环右移. 2. ...

  8. 【转】并查集&MST题集

    转自:http://blog.csdn.net/shahdza/article/details/7779230 [HDU]1213 How Many Tables 基础并查集★1272 小希的迷宫 基 ...

  9. 将Windows上的文件上传到Linux上

    下载一个SSH Secure Shell Client即可. SSHSecureShellClient-3.2.9下载地址: 免费下载地址在 http://linux.linuxidc.com/ 用户 ...

  10. Apache Ignite——新一代数据库缓存系统

    [编者按]飞速增长的数据需要大量存储,对这些数据的管理也不是一件容易的事.但相比于存储和管理,如何处理数据才是开发人员真正的挑战.对于TB级别数据的存储和处理通常会让开发人员陷入速度.可扩展性和开销的 ...