P4008 [NOI2003]文本编辑器 题目描述 很久很久以前,\(DOS3.x\)的程序员们开始对 \(EDLIN\) 感到厌倦.于是,人们开始纷纷改用自己写的文本编辑器⋯⋯ 多年之后,出于偶然的机会,小明找到了当时的一个编辑软件.进行了一些简单的测试后,小明惊奇地发现:那个软件每秒能够进行上万次编辑操作(当然,你不能手工进行这样的测试) !于是,小明废寝忘食地想做一个同样的东西出来.你能帮助他吗? 为了明确目标,小明对"文本编辑器"做了一个抽象的定义: 文本:由 \(0\) 个或…
先推广一下 求赞 我们考虑这样的一个问题 给你一个序列,要求你支持插入,删除,查询单点值 如果用数组,查询O(1),插入删除最坏O(n) 如果用链表,插入删除O(1),查询最坏O(n) 如果用平衡树-- 不要跟我说平衡树 那么我们是否可以考虑:将一个一个的数组以链表的形式串起来,这样是否会提高操作的效率,又是否会降低一些操作的效率呢? 可以手动模拟一下各种操作 块状链表就是这样一个略显暴力的算法 但其复杂度较为优秀,所以在很多地方的应用都非常广 用一句话说叫"弱弱联合" 码量稍大,但极…
LINK:文本编辑器 这个东西感觉块状链表写细节挺多 (块状链表本来就难写 解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n). 这样插入删除的时候直接暴力插入删除即可 复杂度都是根号的. 插入的时候当前的块过大的时候就要分裂 查询时对于大小为0的块记得及时删除即可.(我没写过在口胡 看起来很直观. 但其实这道题 splay来写就好写的多. 插入的话先直接build成一个比较平衡的二叉树 然后直接把对应位置旋到根 把下一个位置旋到根的右儿子 这样插入…
复制炸格式了,就不贴题面了 [NOI2003] 文本编辑器 Solution 对于光标的移动,我们只要记录一下现在在哪里就可以了 Insert操作:手动维护中序遍历结果,即每次取中点像线段树一样一样递归建树,实际操作:把splay中的光标所在位置旋到根,光标后一位旋到根的下面,此时根的右节点的左子树是空的,直接插入我们所建的树的根即可 Delete:先找到我们要删除的是哪一段区间,把光标之前的点旋到根,终点之后的点旋到根的下面,直接扔掉根节点的右儿子的左子树即可 Get:也是找到区间递归中序输出…
思路 FHQ Treap的板子 用FHQ Treap维护中序遍历序列即可 然后数组开够! 代码 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct Node{ int lson,rson,sz,num,ran; }FHQ[300000*30]; int nowpos,n,m,Nodecnt,a[300000*30],root; int new_Node…
本文发布于洛谷日报,特约作者:tiger0132 原地址 分割线下为copy的内容 [洛谷日报第62期]Splay简易教程 洛谷科技 18-10-0223:31 简介 二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树. 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: 若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值:若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值:左.右子树也分别为二叉排序树…
[NOI2003]文本编辑器 没啥好说的 就是个板子 #include <bits/stdc++.h> // #define int long long #define rep(a , b , c) for(int a = b ; a <= c ; ++ a) #define Rep(a , b , c) for(int a = b ; a >= c ; -- a) #define go(u) for(int i = G.head[u] , v = G.to[i] , w = G.…
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269 Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:  文本:由0个或多个字符构成的序列.这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格.光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最…
题目大意:维护一个文本编辑器,支持下列操作: 1.将光标移动到某一位置 2.在光标后插入一段字符串 3.删除光标后的一段字符 4.翻转光标后的一段字符 5.输出光标后的一个字符 6.光标-- 7.光标++ Splay中比較水的一道题,标记仅仅有区间翻转,也不用维护区间总值,只有须要注意的就是插入的时候fa要记得赋值,不然就会像本蒟蒻一样调半天,,, 这题要注意的是Insert操作的读入 首先读入第一个不是'\n'或者'\r'的字符,然后假设长度不为1就继续gets() 记住是get()不是sca…
题目链接 2017.12.24 第一次写: 时间: 2316ms (1268ms) 空间: 19.42MB (19.5MB)(O2) 注:洛谷测的时间浮动比较大 /* 插入一段数:将这些数先单独建一棵平衡树t'.将pos旋到根,pos+1旋到son[root][1],直接将t'放到son[pos+1][0]即可 删除一段数:将要删除区间旋转到r+1的左儿子上,直接删除 统一修改一段数.区间反转:同样,提取修改区间,打标记 区间求和:提取,输出记录的sum 最大子序列:有一种求最大子序列的nlog…
★★★   输入文件:editor2003.in   输出文件:editor2003.out   简单对比 时间限制:2 s   内存限制:128 MB [问题描述] 很久很久以前,DOS3.x的程序员们开始对EDLIN感到厌倦.于是,人们开始纷纷改用自己写的文本编辑器…… 多年之后,出于偶然的机会,小明找到了当时的一个编辑软件.进行了一些简单的测试后,小明惊奇地发现:那个软件每秒能够进行上万次编辑操作(当然,你不能手工进行这样的测试)!于是,小明废寝忘食地想做一个同样的东西出来.你能帮助他吗?…
题目传送门 转载自https://www.cnblogs.com/yousiki/p/6147455.html,转载请注明出处 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 创造者:Daniel Sleator 和 Robert Tarjan 优点:每次查询会调整树的结构,使被查询频率高的条目更靠近树根. Tree Rotation   树的旋转是splay的基础,对于二叉查找树来说,树的旋转不破坏查找树的结构.   Splaying   Splaying是Splay…
题面 洛谷 题解 首先,我们知道求最长公共前缀可以用二分答案+hash来求 因为有修改操作, 考虑将整个字符串的hash值放入splay中 接着就是splay的基本操作了 Code #include<bits/stdc++.h> #define LL long long #define RG register const int N = 500010; typedef unsigned long long ull; using namespace std; inline int gi() {…
题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r',我就被坑了. #include <cstdio> #include <algorithm> using namespace std; inline int read(){ int s = 0, w = 1; char ch = getchar(); while(ch < '0…
https://www.luogu.org/problem/P4008 无旋Treap也可以维护序列. 千万要注意要先判断p节点存在才进行Show操作,不然输出一个'\0'(或者RecBin里面的东西)草. 假如有限制同时存在的节点数量的话,UnBuild操作是显得重要的. 当然这里最主要的是类似笛卡尔树的O(n)建立Treap树. #include<bits/stdc++.h> using namespace std; typedef long long ll; #define ls(p)…
题目链接 st(n)表示sqrt(n) 为使块状链表不会退化,通常将每块的大小S维持在[st(n)/2,2st(n)]中,这样块数C也一定[st(n)/2,2st(n)]中 在此使用另一种方法(方便)维持这种性质:保证任意相邻两块的size相加>st(n),并且每块大小<=st(n) 这样可保证块数C在[st(n),2st(n)]中 在每次块状链表结构改变后执行maintain,顺序扫描链表,将相邻两块能合并就合并 1.注意Insert的读入,会有回车 2.为避免各种翻车,还是加上判断!=-1…
块状链表及其应用 思路楼上已经说的很清楚了 看代码注释 代码很丑 #include<cstdio> #include<cctype> #include<cstring> //#define gc() getchar() #define MAXIN 100000 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) const int N=1024*1024…
1507: [NOI2003]Editor Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1908  Solved: 738[Submit][Status] Description Input 输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作.其中: 为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例). 除了回车符之外,输入文件的所有字符的ASCII码都在…
比较基本的操作. #include<map> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define INF 99999999 #define ll __int64 #define lson l,m,rt<…
练手QAQ #include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> using namespace std; void setIO(const string& a) { freopen((a+".in").c_str(), "r"…
题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N=1e5+5,INF=1e9; int size,root,t[N],sz[N],son[N][2],fa[N],cnt[N]; inline int read() { int now=0,f=1;register char c=getchar(); for(;!isdigit(c);c=getchar())…
题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; int n,m,root,t[N],sz[N],son[N][2],fa[N]; bool tag[N]; inline void Update(int rt) { sz[rt]=sz[son[rt][0]]+sz[son[rt][1]]+1; } inline void Down(int rt) { tag[…
题目链接 //模板吧 #include<cstdio> #include<cctype> #include<algorithm> using namespace std; const int N=40000,INF=1e8; int n,size,root,sz[N],cnt[N],t[N],son[N][2],fa[N]; inline int read() { int now=0,f=1;register char c=getchar(); for(;!isdigi…
题目链接 附纯SplayTLE代码及主要思路: /* 可以看做序列有n段,Insert是每次在每一段最后插入一个元素 只有插入,没有删除,所以插入一个元素对于询问1影响的只有该元素与前边一个元素(同段).下一段的开头元素 故只需删掉该段最后元素与下一段开头元素的差,再加入新元素与下一段开头的差即可 -> 记录差值 对于询问2,将值在平衡树中插入,能有影响的就是相邻两个值了(最小值只可能从中产生) -> 记录值 所以对于每一段只需记录开头与结尾元素,剩下的就是插入删除了 询问2中相邻两个值是前驱…
因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 输入输出格式 输入格式: 输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目. 第 2 行包含 N 个数字,描述初始时的…
题目传送门 营业额统计 题目描述 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题.经济管理学上定义了一种最小波动值来衡量这种情况: 当最小波动值越大时,就说明营业情况越…
题目 发现这样一句话就会导致\(T\) ch[m][0]=++m; 并不是很知道为什么,可能这是某种未定义行为在不同编译器下会有不同后果? 至于这道题就很简单了,几个有关光标位置的操作就用一个变量模拟就好了 插入的话把这个位置转出来构造一棵完美\(splay\)插入就好了 删除直接转出区间断开的父亲的链接 输出直接转出区间中序遍历 代码 #include<algorithm> #include<iostream> #include<cstring> #include&l…
题意 splay维护即可 code: #include<bits/stdc++.h> using namespace std; const int maxn=2000010; int T,tot,points,root; int fa[maxn],size[maxn]; int ch[maxn][2]; char str[maxn],s[maxn]; queue<int>pool; inline int read() { char c=getchar();int res=0,f=1…
题目链接 Splay基础操作 \(Splay\)上的区间翻转 首先,这里的\(Splay\)维护的是一个序列的顺序,每个结点即为序列中的一个数,序列的顺序即为\(Splay\)的中序遍历 那么如何实现区间翻转呢? 对于一次区间翻转操作\(rev(l,r)\),显然先要找到\(l\)和\(r\)在\(Splay\)中的位置 然后把\(l-1\) \(splay\)到根结点,再把\(r+1\) \(splay\)到\(l\)的右儿子的位置 那么区间\([l,r]\)就到了一个子树上,即\(ch[r+…
二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树(baidu百科). 就是一棵二叉树,所有的节点都满足:左子树内每个的点的值比当前点值小,右子树内每个的点的值比当前点值大 如下图 我们只需在树上中序遍历就会得到一个上升的权值序列 我们可以在二叉搜索树上干很多事情,比如插入某个值,查询第k大值,查询某个数的排名等,显然单次操作最坏复杂度为树的深度,…