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. 如何使用SVG及其动画技术为你的 Web 前端开发带来一些新鲜的体验

    任何有开发经验的前端工程师都会考虑到不成体系的设备生态所带来的挑战.设备间不同的屏幕尺寸.分辨率和比例使得产品难以提供一致的体验,对于那些对产品有着像素级完美追求的人这种体验差异尤其显著! SVG(可 ...

  2. 使用CodeMirror插件遇到的问题

    CodeMirror的正常使用: //首先通过<script>标签引入相应的js,这个就不必说了 var myCodeMirror = CodeMirror.fromTextArea(my ...

  3. 零拷贝(Zero-copy) 浅析及其应用

    相信大家都有过面经历,如果跟面试官聊到了操作系统,聊到了文件操作,可能会问你普通的文件读写流程,它有什么缺点,你知道有什么改进的措施.我们经常听说 零拷贝,每次可能只是背诵一些面试要点就过去了,今天我 ...

  4. day23 作业

    day23 作业 目录 day23 作业 1.把登录与注册的密码都换成密文形式 2.文件完整性校验(考虑大文件) 3.注册功能改用json实现 4.项目的配置文件采用configparser进行解析 ...

  5. mysql numeric

    tinyint  1个字节 smallint 2个字节 mediumint 3个字节 int 4个字节 bigint 8个字节

  6. 装机预备技能,Linux系统简介,安装Linux系统,Linux基本操作-云计算学习(2)

    装机预备技能 问题 要求安装一台可用的KVM服务器: RHEL与CentOS系统有什么关联? Linux系统中第三块SCSI硬盘如何表示? 步骤 实现此案例需要按照如下步骤进行. 步骤一:RHEL系统 ...

  7. 最大熵原理(The Maximum Entropy Principle)

    https://wanghuaishi.wordpress.com/2017/02/21/%E5%9B%BE%E8%A7%A3%E6%9C%80%E5%A4%A7%E7%86%B5%E5%8E%9F% ...

  8. Python切图脚本

    背景: 时值疫情,作业需要在网上提交.最近老师改变了交作业方式,之前是提交完整的作业图片即可,现在需要将完整的作业图片切分成一题一题的提交,如果手动切分较麻烦,故本人写了个python脚本实现自动切分 ...

  9. OSCP Learning Notes - Exploit(1)

    Gaining Root with Metasploit Platform: Kali Linux, Kioptrix Level 1 1. Find the IP of Kioptirx nmap ...

  10. python环境搭建及配置

    我选择的是pycharm,这个对新手比较友好 我目前正在自学周志华的西瓜书,在做练习题3.3时需要用到python来实现,做这个练习需要numpy库和matplot库,最开始的时候忘了anaconda ...