luogu P4008 [NOI2003]文本编辑器 splay 块状链表
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 块状链表的更多相关文章
- 洛谷 P4008 [NOI2003]文本编辑器 解题报告
P4008 [NOI2003]文本编辑器 题目描述 很久很久以前,\(DOS3.x\)的程序员们开始对 \(EDLIN\) 感到厌倦.于是,人们开始纷纷改用自己写的文本编辑器⋯⋯ 多年之后,出于偶然的 ...
- [NOI2003] 文本编辑器 (splay)
复制炸格式了,就不贴题面了 [NOI2003] 文本编辑器 Solution 对于光标的移动,我们只要记录一下现在在哪里就可以了 Insert操作:手动维护中序遍历结果,即每次取中点像线段树一样一样递 ...
- 洛谷 P4008 [NOI2003]文本编辑器
先推广一下 求赞 我们考虑这样的一个问题 给你一个序列,要求你支持插入,删除,查询单点值 如果用数组,查询O(1),插入删除最坏O(n) 如果用链表,插入删除O(1),查询最坏O(n) 如果用平衡树- ...
- P4008 [NOI2003]文本编辑器
思路 FHQ Treap的板子 用FHQ Treap维护中序遍历序列即可 然后数组开够! 代码 #include <cstdio> #include <cstring> #in ...
- [NOI2003]文本编辑器 [Fhq Treap]
[NOI2003]文本编辑器 没啥好说的 就是个板子 #include <bits/stdc++.h> // #define int long long #define rep(a , b ...
- 题解 P4008 【[NOI2003]文本编辑器】
块状链表及其应用 思路楼上已经说的很清楚了 看代码注释 代码很丑 #include<cstdio> #include<cctype> #include<cstring&g ...
- [AHOI2006]文本编辑器 Splay tree区间操作
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269 Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个 ...
- BZOJ 1269 文本编辑器 Splay
题目大意:维护一个文本编辑器,支持下列操作: 1.将光标移动到某一位置 2.在光标后插入一段字符串 3.删除光标后的一段字符 4.翻转光标后的一段字符 5.输出光标后的一个字符 6.光标-- 7.光标 ...
- cogs 330. [NOI2003] 文本编辑器
★★★ 输入文件:editor2003.in 输出文件:editor2003.out 简单对比 时间限制:2 s 内存限制:128 MB [问题描述] 很久很久以前,DOS3.x的程序 ...
随机推荐
- 由VIP漂移引发的算法异常问题调查和解决
最近工作中的一个问题,耗时一个月之久终于调查完毕且顺利解决,顿时感慨万千.耗时之久和预期解决时间和环境搭建以及日志不合理等等有关,当然这个并非此文的重点.之所以在很久以后的今天又开始写文,主要是这个问 ...
- gulp 如何排除文件和文件夹
在网上找了好久,很多用gulp-ignore来处理,或者!来处理 经验证,gulp-ignore没有效果,如果有大神路过,还请指教:!一般的写法只能排除单个文件,以下直接写结论 1.如何排除单个文件 ...
- gulp之demo
1.安装gulp cnpm install -g gulp; 2.然后还需要在当前目录安装gulp,具体不详,只知道安装了之后会在当前目录下的node_modules下多一个gulp文件夹 cnpm ...
- Xenon's Attack on the Gangs(树规)
题干 Input Output Example Test 1: Test 2: 3 5 1 2 1 2 2 3 1 3 1 4 3 5 3 10 Tips 译成人话 给n个结点,n-1条无向边.即一棵 ...
- 【Blazor】在ASP.NET Core中使用Blazor组件 - 创建一个音乐播放器
前言 Blazor正式版的发布已经有一段时间了,.NET社区的各路高手也创建了一个又一个的Blazor组件库,其中就包括了我和其他小伙伴一起参与的AntDesign组件库,于上周终于发布了第一个版本0 ...
- Yii2源码分析(一):入口
写在前面,写这些随笔是记录下自己看Yii2源码的过程,可能会有些流水账,大部分解析放在注释里说明,由于个人水平有限,有不正确的地方还望斧正. web入口文件Index.php // 定义全局的常量,Y ...
- Mysql基础(二):MySQL之存储引擎
目录 MySQL之存储引擎 1.MySQL存储引擎介绍 2.MySQL结构 3.MySQL存储引擎分类 4.存储引擎的使用 5.总结 MySQL之存储引擎 1.MySQL存储引擎介绍 MySQL中的数 ...
- javascript基础(一): 浏览器控制台使用Element,console,network,source,application
console https://www.jianshu.com/p/67bcb481d1c5 Element https://www.kkpan.com/article/1845.html
- Python之网络编程 Socket编程
本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实 ...
- 基于SSM框架的简单问答社区
前言:学习了Spring.SpringMVC.MyBatis框架后,开发了一套简单的问答社区,前端采用Bootstrap开发框架. 版本信息 IDEA:2020.1.2 JDK:14.0.1 Mave ...