[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 ...
随机推荐
- Win10正式版激活
参考:https://jingyan.baidu.com/article/47a29f2457af76c015239942.html https://jingyan.baidu.com/article ...
- LeetCode算法1—— 两数之和
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...
- (长期更新)OI常用模板
代码很简单的模板就不收录了. DFT 离散傅立叶变换 void dft(pdd *a,int l,bool r){ int i,j=l/2,k; for(i=1;i<l;++i){ if(i&l ...
- TRANSLATE(转换大/小写并替换字符)
可以将字母 转换大/小 写或使用替 换规则. 要转换大/小 写,请使用 TRANSLATE 语句,用法 如下: 语法 TRANSLATE <c> TO UPPER CASE. TRANSL ...
- [Jmeter]jmeter数据库性能测试配置
学习jmeter过程中,记录一些学习过程中的点点滴滴,用于备忘.本文主要介绍的是如何创建一个简单的测试计划用户测试数据库服务器. 一.添加线程组 二.添加JDBC请求 1.在第一步里面定义并发用户以及 ...
- iOS-Debug Symbol(调试符号)
Debug Symbol(调试符号) 编译警告 从svn下载下来的文件,到处都是编译警告,看着不爽,找下原因,没想到还是一条大鱼 warning: (i386) /UsersLibrary/Devel ...
- 做模态弹框的时候,防止背景滚动方法 移动端 html5
$(window.document).bind("touchmove", function() { return false; });
- 「Haskell 学习」二 类型和函数(上)
随着学习的深入,笔记会补充和修订.当然,这个补充修订也许会鸽,但我一定会坚持写完. 这个笔记假定你至少学过C/C++及Python,或与这两种语言类型相同的语言. 类型系统概述 “Haskell’s ...
- preparedstatement execute()操作成功!但是返回false
转自http://blog.sina.com.cn/s/blog_963fb3af01013rcs.html Connection con = getConn(); String sql2 = &qu ...
- Linux pthread 线程池实现
基于pthread封装了一个简易的ThreadPool,具有以下特性: 1.具有优先级的任务队列 2.线程池大小可以二次调整,增加线程或者删除空闲线程 3.任务两种重写方式,重写run或者使用函数回调 ...