Splay 的区间操作】的更多相关文章

学完Splay的查找作用,发现和普通的二叉查找树没什么区别,只是用了splay操作节省了时间开支. 而Splay序列之王的称号可不是白给的. Splay真正强大的地方是他的区间操作. 怎么实现呢? 我们知道查找树的中序遍历是一个有序的序列.这个时候我们打破查找树左小右大的规则,而是把他的中序遍历作为我们的区间进行维护. 具体来讲有以下操作: 1.建树 2.区间操作[翻转.赋值啊什么的] 3.输出序列 建树 既然是区间,我们可以借鉴线段树的建树 void build(int& u,int l,in…
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269 Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:  文本:由0个或多个字符构成的序列.这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格.光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最…
真的是个神题,蒟蒻表示无力吐槽.刚开始以为是一个板子题,看着题解打了一遍,大概也理解了他是怎么实现的,然后我就去做别的题了,然后就在Three_D大佬的询问下蒙*了.最后还是问的nc哥,并思考了一个中午才搞明白.最主要的一点是,旋转不会改变树的中序遍历. [建树操作] 对于一棵BST,区间[l,r],如果把l-1 splay到根,把r+1 splay到根的右子树,那么[l,r]即为根的右子树的左子树,如果不是BST,这个性质同样适用.然后因为旋转可能会涉及到1,n,所以要建立1,n+2两个哨兵节…
题目大意 维护一个序列,支持两种操作 操作一:将第x个元素的值修改为y 操作二:询问区间[x,y]内的元素的最大值 解题分析 splay的区间操作,事先加入两个编号最小和最大的点防止操作越界. 具体的区间操作类似于线段树. 参考程序 #include <bits/stdc++.h> using namespace std; const int INF=2000000000; const int N=200008; int a[N]; class splay_tree { public: str…
到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) 了. 忽然回想起之前大佬的一幕幕, 有一丝惆怅 真的不知道该怎么安慰dalao... 不过上天不会忽视那些默默努力的人的对吧 不想被说做作, 但是如果dalao能看到这篇博客的话, 大佬, 高考加油啊 为什么在这里写这些呢? \(Splay\) 其实是大佬领进门的, 学习的也是大佬的板子, 大佬很久…
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置.不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1.X或X+1本书. 当然也有特殊情况,…
据大佬说,\(Splay\)是序列操作之王.\(Splay\)是一种平衡树,通过伸展(\(Splay\)),在不改变中序遍历的前提下变换根的位置,从而快速的进行序列操作 \(Splay\)最常见的序列操作是序列反转了:给定一段区间\([L,R]\),要求反转这一段区间 一次\(Splay\)操作复杂度:均摊\(O(\log\ N)\) 一般情况下:我们对一段区间这样操作:选定\(L - 1\)这个节点,Splay到\(root\),因为\(R\)在\(L\)右边,所以现在\(R\)一定在根(\(…
题目链接:http://poj.org/problem?id=3468 以前用线段树做过,现在用Splay Tree A了,向HH.kuangbin.cxlove大牛学习了各种Splay各种操作,,,Orz.. Splay Tree的区间操作和线段树的操作差不多,也是保存子树的值,然后懒惰操作,在Rotate()最后维护节点信息的时候,只要Push_Up(y)的,因为x还需要网上旋转到根节点,最后更新下就可以了,并且在下一次Rotate()的时候,还会Push_Down(x)的信息,因此不能Pu…
前几天刚刚自学了一下splay,发现思路真简单实现起来好麻烦 先贴一下头文件 # include <stdio.h> # include <stdlib.h> # include <iostream> # include <string.h> # define ll long long # define RG register//卡常 # define IL inline//再卡常 # define UN unsigned # define mem(a, b…
很神奇的旋转操作. 目前没看到其他数据结构能实现这个功能.平衡树不好处理区间操作,线段树很难旋转.splay tree搞这个就很简单了. 下面用的这个模板跑了700ms,好慢,估计是删除操作太费时了,是时候去找找其他更快的模板了. #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; #define MAXN 1…
splay是支持区间操作的,先做这道题入个门 大多数操作都和普通splay一样,就不多解释了,只解释一下不大一样的操作 #include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f inline int read(){ ,f=; char ch=getchar(); '){ ; ch=getchar(); } '){ w=(w<<)+(w<<)+ch-; ch=getchar(); } retur…
题意:给你一些区间操作,让你输出最后得出的区间. 解法:区间操作的经典题,借鉴了网上的倍增算法,每次将区间乘以2,然后根据区间开闭情况做微调,这样可以有效处理开闭区间问题. 线段树维护两个值: cov 和 rev  ,一个是覆盖标记,0表示此区间被0覆盖,1表示被1覆盖,-1表示未被覆盖, rev为反转标记,rev = 1表示反转,0表示不翻转 所以集合操作可以化为如下区间操作: U l r:   把区间[l,r]覆盖成1I  l r:   把[0,l)(r,MAX]覆盖成0 D l r:  …
Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)Total Submission(s): 3830    Accepted Submission(s): 940 Problem Description Yuanfang is puzzled with the question below: There are n integers, a1, a2,…
涉及区间操作的一些套路必须要会呀 区间加减为了偷懒能不写线段树so我选择树状数组!! 但是区间乘除,最大值我想了想还是用线段树分块吧. 树状数组: 这里用网上的一张图: 这里灰色数组是原本的数组(a[i])红色数组则是树状数组(c[i])这里直接给出结论: c[i]=a[i-2^k+range[1,2^k]] k是i的二进制位从低到高位连续0的个数 与a[i]有关的 c[i+2^(k+j)] 且 i+2^(j+k)<n 这样就很好实现单点更改,区间查询了. void lowbit(int x)…
题面: 1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 5367  Solved: 2323[Submit][Status][Discuss] Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题…
首先基本操作如下: 删除第rank个点 void Remove(int id){//删除第rank个点 rank++; int x = find(root, rank - 1); splay(x, 0); x = find(root, rank + 1); splay(x, root); ch[ch[root][1]][0] = 0; pushup(ch[root][1]),pushup(root); } 删除编号为id的点 void Remove(int id){//删除编号为id的点 spl…
题意:实现一种数据结构,支持对一个数列的 6 种操作:第 x 个数到第 y 个数之间的数每个加 D:第 x 个数到第 y 个数之间全部数翻转:第 x 个数到第 y 个数之间的数,向后循环流动 c 次,即后面 c个数变成这段子序列的最前面 c 个,前面的被挤到后面.在第 x 个数后面插入一个数 P.删除第 x 个数.求第 x 个数到第 y 个数之间的最小数字. 题解: (待补) 代码先放上: (是真的长啊,我已经是比较压行的选手了,依然写了230行) 1.利用stack回收内存池 #include…
Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目. 第2行包含N个数字,描述初始时的数列. 以下M行,每行一条命令,格式参见问题描述中的表格. 任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内. 插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes. Output 对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次…
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1500 Description Input 输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目. 第2行包含N个数字,描述初始时的数列. 以下M行,每行一条命令,格式参见问题描述中的表格. Output 对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行. Sample Input 9 8 2 -6 3 5…
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 对于一个数列有两种操作:1.CUT a b c,先取出a-b区间的数,然后把它们放在取出后的第c个数后面.2.FLIP a b,把区间a-b的数反转.对于第一个操作,进行两次区间移动,第a-1个数Splay到根节点,b+1个数Splay到root的右儿子,ch[ch[root][1]][0]则表示那个区间,然后把它们除掉,然后在移动区间,把第c个数Splay到root,第c+1个数Splay到…
题意:对数组进行各种操作 其中 REVOLVE右移操作.将区间[a,b]右移c位 首先c可能比较多,可以先对区间长度取模. 在右移之后,可以发现[a,b]被分为两个区间[a,b-c]  [b-c+1,b],将后者插入到前者之前即可. // File Name: ACM/POJ/3580.cpp // Author: Zlbing // Created Time: 2013年08月10日 星期六 10时51分07秒 #include<iostream> #include<string>…
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2202  Solved: 1226[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次…
传送门:>Here< 解法分析 用splay来维护这个序列. 一直没有搞明白的是,这里的splay的节点究竟维护的是什么?是权值吗?肯定不是,因为区间是会翻转的,如果维护权值的话很快平衡树就不再满足性质. 然而从头到尾,唯一始终统一的就是位置——始终是1~n. 因此考虑用节点来维护位置. 这样在维护splay的时候,翻转一段区间就相当于修改了这一段区间的位置,使原来小的现在大了,原来大的现在小了.放在树上形象的看,就是原来作为父节点的左儿子的统统称为了右儿子.反之亦然.因此只要找出连续的那一段…
题面: #1333 : 平衡树·Splay2 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:好麻烦啊~~~~~ 小Hi:小Ho你在干嘛呢? 小Ho:我在干活啊!前几天老师让我帮忙管理一下团队的人员,但是感觉好难啊. 小Hi:说来听听? 小Ho:事情是这样的.我们有一个运动同好会,每天都有人加入或者退出,所以老师让我帮忙管理一下人员.每个成员有一个互不相同的id和他对我们同好会的兴趣值val,每隔一段时间一些成员的兴趣值就会发生变化.老师有时候也会问我一些成…
这题的建模有点不太一样,是按结点横坐标赋予键值的 同时每次rotate和splay时都要注意下往上往下更新 /* 先建立好splay tree,将结点按num/输入顺序排序,遍历时每次将当前结点提到根节点,输出其在splay树中排第几个 然后rev左子树,最后remove */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; #include<algorithm&…
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6881  Solved: 4213[Submit][Status][Discuss] Description   您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列…
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 N,M<=100000 Sample Output4 3 2 1 5 Hint Input 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数 接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n Output 输出一行n个数字,表示原始序列…
bzoj1251权限题 题目点这里,你懂得 直接上板子,这个要好好体会 操作是最经典的. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <…
题目传送门 题意:四种集合的操作,对应区间的01,问最后存在集合存在的区间. 分析:U T [l, r]填充1; I T [0, l), (r, N]填充0; D T [l, r]填充0; C T[0, l), (r, N]填充0并且[l, r]xor; S T [l, r]xor 线段树结点两个属性,cover[o]: 该区间是否填充(1, 0, -1),_xor[o]: 该区间是否异或反转(1, 0).最后(和[的区别可以原数*2判奇偶得 #include <cstdio> #includ…
/* 题意:给定一个长度为n的序列a. 两种操作: 1.给定区间l r 加上某个数x. 2.查询区间l r sigma(fib(ai)) fib代表斐波那契数列. 思路: 1.矩阵操作,由矩阵快速幂求一个fib数根据矩阵的乘法结合率,A*C+B*C=(A+B)*C; 这样可以通过线段树维护某个区间2*1矩阵的和. 2.时限卡的紧...用我的矩阵乘法板子TLE了.所以把板子里边的三重循环改成手工公式... 3.注意(a+b)%mod.这种,改成if(a+b>=mod)a+b-mod这种形式时间几乎…