[NOI2003] 文本编辑器 (splay)
复制炸格式了,就不贴题面了
[NOI2003] 文本编辑器
Solution
对于光标的移动,我们只要记录一下现在在哪里就可以了
Insert操作:手动维护中序遍历结果,即每次取中点像线段树一样一样递归建树,实际操作:把splay中的光标所在位置旋到根,光标后一位旋到根的下面,此时根的右节点的左子树是空的,直接插入我们所建的树的根即可
Delete:先找到我们要删除的是哪一段区间,把光标之前的点旋到根,终点之后的点旋到根的下面,直接扔掉根节点的右儿子的左子树即可
Get:也是找到区间递归中序输出就可以了
提示:为了防止越界,我在splay插入了两个换行符,保证题目输入不会出现就行,因此也要把光标初始值设为1
Code
#include<bits/stdc++.h>
#define il inline
#define rg register
#define lol long long
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
using namespace std;
const int N=1e6+10;
const int inf=2e9;
void in(int &ans)
{
ans=0; int f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0', i=getchar();
ans*=f;
}
int n,tot,m,now=1,root;
char s[N<<1];
struct Splay {
int f,size,ch[2];
Splay(){
size = ch[0] = ch[1] = 0;
}
char val;
}t[N<<1];
il bool get(int x) {
return t[t[x].f].ch[1]==x;
}
il void up(int x) {
t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1;
}
void rotate(int x) {
int f=t[x].f,gf=t[f].f;
int k1=get(x),k2=get(f);
t[gf].ch[k2]=x,t[x].f=gf;
t[f].ch[k1]=t[x].ch[k1^1],t[t[x].ch[k1^1]].f=f;
t[x].ch[k1^1]=f,t[f].f=x;
up(f); up(x);
}
void splay(int x,int goal) {
while(t[x].f!=goal) {
int f=t[x].f,gf=t[f].f;
if(gf!=goal) get(x)^get(f)?rotate(x):rotate(f);
rotate(x);
}
if(!goal) root=x;
}
int kth(int k) {
int u=root;
while(1) {
int y=t[u].ch[0];
if(k>t[y].size+1)
u=t[u].ch[1],k-=t[y].size+1;
else if(k<=t[y].size) u=y;
else return u;
}
}
il void Move() {
in(now); now++;
}
il int add(char c,int f) {
t[++tot].val=c; t[tot].size=1;
t[tot].f=f; return tot;
}
int build(int f,int l,int r,char *s) {
int mid=l+r>>1;
char ch=s[mid];
int u=add(ch,f);//按中序遍历建树
if(l<mid) t[u].ch[0]=build(u,l,mid-1,s);
if(mid<r) t[u].ch[1]=build(u,mid+1,r,s);
up(u); return u;
}
void Insert() {
int x; in(x); strcpy(s,"");
for(rg int i=1;i<=x;i++) {
char ch=getchar();
while(ch==10 || ch==13 || ch<32 || ch>126) ch=getchar();
s[i]=ch;
}
int l=kth(now);
int r=kth(now+1);
splay(l,0); splay(r,l);
t[t[root].ch[1]].ch[0]=build(t[root].ch[1],1,x,s);
up(t[root].ch[1]); up(root);
}
void Delete() {
int x; in(x);
int l=kth(now),r=kth(now+x+1);//r=kth((now+x-1)+1+1)第一个+1指光标指到起点,因为实际上光标指的是起点-1所以要加回来,第二个+1指区间终点的后一个端点
splay(l,0); splay(r,l);
int u=t[root].ch[1];
t[u].ch[0]=0;
up(u); up(root);
}
void out(int u) {
if(t[u].ch[0]) out(t[u].ch[0]);
if(t[u].val!='\n') putchar(t[u].val);
if(t[u].ch[1]) out(t[u].ch[1]);
}
void Get() {
int x; in(x);
int l=kth(now),r=kth(now+x+1);
splay(l,0); splay(r,l);
out(t[t[root].ch[1]].ch[0]);
putchar('\n');
}
int main()
{
//freopen("data.in", "r", stdin);
root=add('\n',0),t[root].ch[1]=add('\n',root);up(root);
in(n); char s[10];
while(n--) {
scanf("%s",s);
if(s[0]=='M') Move();
if(s[0]=='I') Insert();
if(s[0]=='D') Delete();
if(s[0]=='G') Get();
if(s[0]=='P') now--;
if(s[0]=='N') now++;
}
return 0;
}
博主蒟蒻,随意转载.但必须附上原文链接
http://www.cnblogs.com/real-l/
[NOI2003] 文本编辑器 (splay)的更多相关文章
- luogu P4008 [NOI2003]文本编辑器 splay 块状链表
LINK:文本编辑器 这个东西感觉块状链表写细节挺多 (块状链表本来就难写 解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n). 这样插入删除的时候直接暴 ...
- 洛谷 P4008 [NOI2003]文本编辑器 解题报告
P4008 [NOI2003]文本编辑器 题目描述 很久很久以前,\(DOS3.x\)的程序员们开始对 \(EDLIN\) 感到厌倦.于是,人们开始纷纷改用自己写的文本编辑器⋯⋯ 多年之后,出于偶然的 ...
- [NOI2003]文本编辑器 [Fhq Treap]
[NOI2003]文本编辑器 没啥好说的 就是个板子 #include <bits/stdc++.h> // #define int long long #define rep(a , b ...
- [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的程序 ...
- 【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)
题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r ...
- NOI2003 文本编辑器editor
1507: [NOI2003]Editor Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 1908 Solved: 738[Submit][Statu ...
- HYSBZ 1269文本编辑器 splay
比较基本的操作. #include<map> #include<queue> #include<stack> #include<cmath> #incl ...
随机推荐
- python读取大文件和普通文件
读取文件,最常见的方式是: with open('filename', 'r', encoding = 'utf-8') as f: for line in f.readlines(): do_som ...
- HBase 高级架构解析
整体框架 使用 ZooKeeper 框架协助 RegionServer(类似于HDFS的nodemanager)用户请求从 Client 到 Zookeeper 进行判断数据属于哪一个 Region ...
- PRO*C 函数事例 1 -- 数据库连接、事务处理
1.程序结构 每一个Pro*C程序都包括两部分:(1)应用程序首部:(2)应用程序体 应用程序首部定义了ORACLE数据库的有关变量, 为在C语言中操纵ORACLE数据库做 ...
- Cadence17.2下载ALTERA的FPGA封装库
1. 在Cadence的安装目录里面找了下,发现都没有Altera的FPGA型号的函数库,下面的虽然是ALTERA,但是没有FPGA的器件封装 2. 去intel的官网看能不能下载到,INTEL网址, ...
- java使用java.util.Properties读取properties文件的九种方法
直接上代码: package com.test.test; import java.io.BufferedInputStream; import java.io.FileInputStream; im ...
- Ubuntu 添加中文字体
查看系统类型 cat /proc/version 查看中文字体 fc-list :lang=zh-cn 安装字体 sudo apt install -y --force-yes --no-instal ...
- React切换显示和隐藏
1 {radioChange >= 0 && 2 <div> 3 {radioChange === 0 ? ( 4 <div className={style. ...
- Qt irrlicht(鬼火)3D引擎 摄像机旋转问题
点击打开链接Irrlicht中的摄像有一个函数 setUpVector() if (m_device != 0 ) { core::vector3df rotation(y,x,0.f); m_cam ...
- Django 运行Admin 页面时出现 UnicodeDecodeError: 'gbk' codec can't decode byte XXXX解决方法
具体报错信息 Traceback (most recent call last): File "D:\Anaconda3\lib\site-packages\django\core\hand ...
- [PocketFlow]解决TensorFLow在COCO数据集上训练挂起无输出的bug
1. 引言 因项目要求,需要在PocketFlow中添加一套PeleeNet-SSD和COCO的API,具体为在datasets文件夹下添加coco_dataset.py, 在nets下添加pelee ...