LINK:文本编辑器

这个东西感觉块状链表写细节挺多 (块状链表本来就难写

解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n).

这样插入删除的时候直接暴力插入删除即可 复杂度都是根号的。

插入的时候当前的块过大的时候就要分裂 查询时对于大小为0的块记得及时删除即可。(我没写过在口胡

看起来很直观。

但其实这道题 splay来写就好写的多。

插入的话先直接build成一个比较平衡的二叉树 然后直接把对应位置旋到根 把下一个位置旋到根的右儿子 这样插入的时候插到右儿子的左儿子上即可。

删除 查询同理。

前驱和后继 这个直接在splay上暴力寻找就行 反正期望复杂度logn.

Move操作的话需要记录一下某个点的子树大小在splay上跑就行了。

细节也不多 算是比较好写。

//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 5000000000000000000ll
#define ldb long double
#define pb push_back
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define mod 1000000007
#define S second
#define F first
#define gf(x) scanf("%lf",&x)
#define ull unsigned long long
#define ui unsigned
#define pf push_front
#define pb push_back
#define popf pop_front
#define l(p) c[p][0]
#define r(p) c[p][1]
using namespace std;
const int MAXN=2000010;
int rt,n,id,top;
int c[MAXN][2],f[MAXN],sz[MAXN],q[MAXN];
char a[10],w[MAXN];
inline void pushup(int p)
{
sz[p]=sz[l(p)]+sz[r(p)]+1;
return;
}
inline int build(int l,int r)
{
if(l>r)return 0;
int mid=(l+r)>>1;
c[q[mid]][0]=build(l,mid-1);
c[q[mid]][1]=build(mid+1,r);
if(c[q[mid]][0])f[c[q[mid]][0]]=q[mid];
if(c[q[mid]][1])f[c[q[mid]][1]]=q[mid];
pushup(q[mid]);return q[mid];
}
inline int get_nex(int x)
{
x=c[x][1];
while(c[x][0])x=c[x][0];
return x;
}
inline void rotate(int x)
{
int old=f[x],oldf=f[old],k=c[old][1]==x;
c[old][k]=c[x][k^1];c[x][k^1]=old;
if(oldf)c[oldf][c[oldf][1]==old]=x;
if(c[old][k])f[c[old][k]]=old;
f[old]=x;f[x]=oldf;pushup(old);
}
inline void splay(int x,int y)
{
while(f[x]!=y)
{
int old=f[x];
if(f[old]!=y)rotate(((c[f[old]][1]==old)^(c[old][1]==x))?x:old);
rotate(x);
}
pushup(x);if(!y)rt=x;
}
inline int find(int x)
{
int ww=rt;
while(1)
{
if(sz[l(ww)]+1==x)return ww;
if(sz[l(ww)]>=x)ww=l(ww);
else x=x-sz[l(ww)]-1,ww=r(ww);
}
return -1;
}
inline void get_data(int x)
{
if(!x)return;
get_data(c[x][0]);
q[++top]=x;
get_data(c[x][1]);
}
inline int get_pre(int x)
{
x=c[x][0];
while(c[x][1])x=c[x][1];
return x;
}
int main()
{
//freopen("1.in","r",stdin);
gt(n);rt=++id;sz[id]=2;++id;c[1][1]=id;sz[id]=1;f[id]=1;
rep(1,n,i)
{
gc(a);
if(a[1]=='I')
{
int x;gt(x);top=0;
char ch=getchar();
while(x)
{
ch=getchar();
while((int)ch<32||(int)ch>126)ch=getchar();
w[++id]=ch;q[++top]=id;--x;
}
int ww=build(1,top);
int w1=get_nex(rt);splay(w1,rt);
c[w1][0]=ww;f[ww]=w1;pushup(w1);pushup(rt);
}
if(a[1]=='M')
{
int x;gt(x);++x;
int w=find(x);
splay(w,0);
}
if(a[1]=='D')
{
int x;gt(x);
x=sz[l(rt)]+1+x+1;
int ww=find(x);
splay(ww,rt);
c[ww][0]=0;
pushup(ww);pushup(rt);
}
if(a[1]=='G')
{
int x;gt(x);
x=sz[l(rt)]+1+x+1;
int ww=find(x);
splay(ww,rt);
top=0;get_data(c[ww][0]);
rep(1,top,i)printf("%c",w[q[i]]);
puts("");
}
if(a[1]=='P')splay(get_pre(rt),0);
if(a[1]=='N')splay(get_nex(rt),0);
}
return 0;
}

luogu P4008 [NOI2003]文本编辑器 splay 块状链表的更多相关文章

  1. 洛谷 P4008 [NOI2003]文本编辑器 解题报告

    P4008 [NOI2003]文本编辑器 题目描述 很久很久以前,\(DOS3.x\)的程序员们开始对 \(EDLIN\) 感到厌倦.于是,人们开始纷纷改用自己写的文本编辑器⋯⋯ 多年之后,出于偶然的 ...

  2. [NOI2003] 文本编辑器 (splay)

    复制炸格式了,就不贴题面了 [NOI2003] 文本编辑器 Solution 对于光标的移动,我们只要记录一下现在在哪里就可以了 Insert操作:手动维护中序遍历结果,即每次取中点像线段树一样一样递 ...

  3. 洛谷 P4008 [NOI2003]文本编辑器

    先推广一下 求赞 我们考虑这样的一个问题 给你一个序列,要求你支持插入,删除,查询单点值 如果用数组,查询O(1),插入删除最坏O(n) 如果用链表,插入删除O(1),查询最坏O(n) 如果用平衡树- ...

  4. P4008 [NOI2003]文本编辑器

    思路 FHQ Treap的板子 用FHQ Treap维护中序遍历序列即可 然后数组开够! 代码 #include <cstdio> #include <cstring> #in ...

  5. [NOI2003]文本编辑器 [Fhq Treap]

    [NOI2003]文本编辑器 没啥好说的 就是个板子 #include <bits/stdc++.h> // #define int long long #define rep(a , b ...

  6. 题解 P4008 【[NOI2003]文本编辑器】

    块状链表及其应用 思路楼上已经说的很清楚了 看代码注释 代码很丑 #include<cstdio> #include<cctype> #include<cstring&g ...

  7. [AHOI2006]文本编辑器 Splay tree区间操作

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269 Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个 ...

  8. BZOJ 1269 文本编辑器 Splay

    题目大意:维护一个文本编辑器,支持下列操作: 1.将光标移动到某一位置 2.在光标后插入一段字符串 3.删除光标后的一段字符 4.翻转光标后的一段字符 5.输出光标后的一个字符 6.光标-- 7.光标 ...

  9. cogs 330. [NOI2003] 文本编辑器

    ★★★   输入文件:editor2003.in   输出文件:editor2003.out   简单对比 时间限制:2 s   内存限制:128 MB [问题描述] 很久很久以前,DOS3.x的程序 ...

随机推荐

  1. 大厂前端带来css3动画transition的使用和介绍全新认识动画

    CSS3中可以使用transition来做最简单动画效果,transition表示到一个元素的属性值发生变化时,我们可以看到页面元素从旧的属性慢慢变化为新的属性值的过程,这种效果不是立即变化的,而是体 ...

  2. 区间dp(能量项链)

    [题目大意] 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记 ...

  3. mysql 存储引擎的选择

    MyISAM:如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性.并发性要求不是很高,选择这个存储引擎非常合适.MyISAM在Web.数据仓储和其他应用环境下最常使用的存储 ...

  4. DVWA学习记录 PartⅡ

    Command Injection 1. 题目 Command Injection,即命令注入,是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的. 2. Low a. 代码分析 ...

  5. Scala 面向对象(六):面向对象的特征二:继承 (一)

    1 Scala继承的基本语法 class 子类名 extends 父类名 { 类体 } class Person { var name : String = _ var age : Int = _ d ...

  6. JVM 专题二十:垃圾回收(四)垃圾回收器 (一)

    1. GC分类与性能指标 垃圾收集器没有在规范中进行过多的规定,可以由不同的厂商.不同版本的JVM来实现.由于JDK的版本处于高速迭代过程中,因此Java发展至今已经产生了众多的GC版本.从不同角度分 ...

  7. Apache Hudi重磅特性解读之存量表高效迁移机制

    1. 摘要 随着Apache Hudi变得越来越流行,一个挑战就是用户如何将存量的历史表迁移到Apache Hudi,Apache Hudi维护了记录级别的元数据以便提供upserts和增量拉取的核心 ...

  8. 句柄Handle的释放(8)

    本篇首先介绍几个与句柄分配与释放密切相关的类,然后重点介绍句柄的释放. 1.HandleArea.Area与Chunk 句柄都是在HandleArea中分配并存储的,类的定义如下: // Thread ...

  9. js自定义获取浏览器宽高

    /** * @description js自定义获取浏览器宽高 * * IE8 和 IE8 以下的浏览器不兼容 * window.innerWidth * window.innerHeight * * ...

  10. 【Python学习笔记二】开始学习啦!如何在IDEA中新建python文件

    1.新建module   2.选择本地安装的python   3.右键新建的module,创建python file就可以开始编程了   4.有时候回出现无法识别python内建函数的问题,就是运行没 ...