2012年4月1日
摘要: HDU_3487 拿这个题目练了一下splay的区间的切割,也就是删除、移动、添加一个连续的区间。#include<stdio.h>#include<string.h>#define MAXD 300010int N, M, T, node, size[MAXD], rev[MAXD], left[MAXD], right[MAXD], pre[MAXD], key[MAXD], ans[MAXD], P;void newnode(int &cur, int k){ cur = ++ node; key[cur] = k; size[cur] = 1; rev[ 阅读全文
posted @ 2012-04-01 18:38 Staginner 阅读(393) 评论(0) 推荐(0) 编辑
摘要: HDU_3436 这个题目无论用什么方法做,首先离散化时候一定要处理好,否则后面会越想越乱。一个比较好的离散化的思路就是把需要Top和Query点看成一个小区间,然后把这些点之间的部分,以及头尾两个部分看成其他的一个一个的区间。 线段树或者树状数组的做法可以参考http://www.cppblog.com/Yuan/archive/2010/08/18/123871.html,我就只说一下用splay的思路吧。维护splay只需要维护一个size,但这个size表示的不是子树的节点数,而是子树上的所有区间所包含的点的总数。 对于top操作,由于我们要先找到那个点(或者说是小区间)的节点标号(. 阅读全文
posted @ 2012-04-01 17:08 Staginner 阅读(732) 评论(0) 推荐(1) 编辑
摘要: HDU_1890 第一次写涉及到区间翻转的splay,结果就没注意到翻转的操作类似于线段树中对区间0、1取反的操作,下传标记的时候记录翻转的标记rev应该是加1模2,而不能简单地将左右儿子的rev置为1。 下面说说具体的思路吧。 我们每次可以先将“最小”的点旋转到根,那么根左边的区间自然就是要翻转的区间了,于是我们对根左边的区间打上翻转的标记,然后将根删除,如此反复N-1遍。对于每次要输出的值,假设我们现在试图令第i个block到位,那么把这个点旋转到根后,输出i+size[left[T]]即可,其中T表示根。当然,最后还要输出一个N。 然而,我们要如何知道每次该旋转哪个block呢?即便.. 阅读全文
posted @ 2012-04-01 01:17 Staginner 阅读(1540) 评论(0) 推荐(0) 编辑