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. sass安装与教程

    首先下载ruby http://dlsw.baidu.com/sw-search-sp/soft/ff/22711/rubyinstaller_V2.2.2.95_setup.1439890355.e ...

  2. Linux系统中虚拟设备文件的各种实用用法

    大家好,我是良许. 大家知道,在 Linux 下,一切皆文件,对于设备文件也是如此.我们在工作的过程中,经常会看到 /dev/null 这个玩意,那它到底是什么呢? 专业地讲,/dev/null 是一 ...

  3. python写12306抢票

    #!/usr/bin/env python # -*- coding: utf-8 -*- ''' 利用splinter写的一个手动过验证及自动抢票的例子, 大家可以自己扩展或者弄错窗体.web端. ...

  4. day16 三层装饰器和迭代器

    一. 经典的两层装饰器,也是标准装饰器 案例 import time def outter1(func): def wrapper(*args, **kwargs): start = time.tim ...

  5. python爬虫拉钩网:{'msg': '您操作太频繁,请稍后再访问', 'clientIp': '113.57.176.181', 'success': False}

    反爬第一课: 在打印html.text的时候总会提示 {'success': False, 'msg': '您操作太频繁,请稍后再访问', 'clientIp': '113.14.1.254'} 需要 ...

  6. CSS背景处理

    CSS背景处理 背景样式 背景颜色 如果想让一个区域具有纯色的背景,可以使用background-color进行设置,背景颜色可以是rgb,rgba,#16网页色. <!DOCTYPE html ...

  7. 将ipynb文件转换为markdown

    jupyter nbconvert --to markdown "3.11-matplotlib 基础.ipynb"

  8. HLS的M3U8文件介绍

    HLS的M3U8文件介绍 HLS (HTTP Live Streaming)是Apple的动态码率自适应技术.主要用于PC和Apple终端的音视频服务. 相较于实时传输协议(RTP),HLS可以穿过任 ...

  9. 关于Excel去空格问题

    做开发,导入导出是一项基本功能,基本每个系统都有. 导入日期字段难免碰到因为空格问题引起的日期格式化Bug 下面分享一项Excel识别空格以及去空格的方法. 一:识别空格技巧(不要相信你的眼睛,有些空 ...

  10. 一次HTTP请求服务的完整过程-请求处理过程

    0.DNS域名解析:递归查询.迭代查询 递归查询:客户端向第一个服务器查询,给最终结果 迭代查询:第一个服务器向根查询 1 .建立连接:接收或拒绝连接请求:三次握手的过程 提高HTTP 连接性能: 并 ...