[NOI2003]文本编辑器/[AHOI2006]文本编辑器
XII.初级版:[NOI2003]文本编辑器;进阶版:[AHOI2006]文本编辑器
两道题操作基本一致,唯一的区别就是进阶版多了一个翻转操作,因此干脆合在一起讲。
可以使用splay或fhq treap通过。个人认为fhq treap更加直观。
光标的位置,我们用一个值表示。
Move/Next/Prev
:直接修改的值即可。
Insert
:笛卡尔树建树并插入。
Delete
:split
出有效区间然后删掉即可。可以采取空间回收,这是很好的习惯,因为你不知道会不会RE/MLE。
Get
:直接输出split
后右半部最靠左那个地方的字符即可。
Rotate
:fhq treap上打区间翻转的tag即可。
#include<bits/stdc++.h>
using namespace std;
int n,rt,cnt,bin[5001000],tp,tar,stk[5001000],bd;
char s[5001000];
void getstring(int len){
char c=getchar();
for(int i=0;i<len;i++){
while(c>126||c<32)c=getchar();
s[i]=c,c=getchar();
}
}
int read(){
int x=0;
char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')x=x*10+c-48,c=getchar();
return x;
}
struct treap{
int lson,rson,rd,sz;
char ch;
}t[5001000];
int newnode(char ch){
int x=tp?bin[tp--]:++cnt;
t[x].ch=ch,t[x].lson=t[x].rson=0,t[x].sz=1,t[x].rd=rand()*rand();
return x;
}
void pushup(int x){
t[x].sz=1;
if(t[x].lson)t[x].sz+=t[t[x].lson].sz;
if(t[x].rson)t[x].sz+=t[t[x].rson].sz;
}
void split(int x,int k,int &u,int &v){
if(!x){u=v=0;return;}
if(t[t[x].lson].sz>=k)v=x,split(t[x].lson,k,u,t[x].lson);
else u=x,split(t[x].rson,k-t[t[x].lson].sz-1,t[x].rson,v);
pushup(x);
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(t[x].rd>t[y].rd){t[x].rson=merge(t[x].rson,y),pushup(x);return x;}
else{t[y].lson=merge(x,t[y].lson),pushup(y);return y;}
}
void iterate(int x){
if(!x)return;
iterate(t[x].lson);
putchar(t[x].ch);
iterate(t[x].rson);
}
void oldnode(int x){
if(!x)return;
oldnode(t[x].lson),oldnode(t[x].rson),bin[++tp]=x;
}
int build(int len){
int las;
for(int i=0;i<len;i++){
int x=newnode(s[i]);
las=0;
while(bd&&t[stk[bd]].rd<t[x].rd)pushup(stk[bd]),las=stk[bd--];
if(bd)t[stk[bd]].rson=x;
t[stk[++bd]=x].lson=las;
}
while(bd)pushup(stk[bd--]);
return stk[1];
}
void Move(){tar=read();}
void Insert(){
int len=read();
getstring(len);
int a,b;
split(rt,tar,a,b);
rt=merge(merge(a,build(len)),b);
}
void Delete(){
int len=read();
int a,b,c;
split(rt,tar,a,b);
split(b,len,b,c);
oldnode(b);
rt=merge(a,c);
}
void Get(){
int len=read();
int a,b,c;
split(rt,tar,a,b);
split(b,len,b,c);
iterate(b);putchar('\n');
rt=merge(merge(a,b),c);
}
void Prev(){tar--;}
void Next(){tar++;}
int main(){
n=read();
while(n--){
scanf("%s",s);
if(s[0]=='I')Insert();
else if(s[0]=='M')Move();
else if(s[0]=='D')Delete();
else if(s[0]=='G')Get();
else if(s[0]=='P')Prev();
else if(s[0]=='N')Next();
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,stk[5001000],tp,bin[5001000],bd,cnt,tar,rt;
char s[5001000];
void getstring(int len){
for(int i=0;i<len;i++)s[i]=getchar();
}
int read(){
int x=0;
char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x;
}
struct treap{
int lson,rson,rd,sz;
char ch;
bool rev;
}t[5001000];
int newnode(char ch){
int x=tp?bin[tp--]:++cnt;
t[x].lson=t[x].rson=0,t[x].rd=rand()*rand(),t[x].sz=1,t[x].ch=ch,t[x].rev=false;
return x;
}
void oldnode(int x){
if(!x)return;
oldnode(t[x].lson),oldnode(t[x].rson),bin[++tp]=x;
}
void pushup(int x){
t[x].sz=1;
if(t[x].lson)t[x].sz+=t[t[x].lson].sz;
if(t[x].rson)t[x].sz+=t[t[x].rson].sz;
}
void REV(int x){
swap(t[x].lson,t[x].rson),t[x].rev^=1;
}
void pushdown(int x){
if(!t[x].rev)return;
REV(t[x].lson),REV(t[x].rson),t[x].rev=false;
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(t[x].rd>t[y].rd){pushdown(x),t[x].rson=merge(t[x].rson,y),pushup(x);return x;}
else{pushdown(y),t[y].lson=merge(x,t[y].lson),pushup(y);return y;}
}
void split(int x,int k,int &u,int &v){
if(!x){u=v=0;return;}
pushdown(x);
if(t[t[x].lson].sz>=k)v=x,split(t[x].lson,k,u,t[x].lson);
else u=x,split(t[x].rson,k-t[t[x].lson].sz-1,t[x].rson,v);
pushup(x);
}
void Insert(){
int len=read();
getstring(len);
for(int i=0;i<len;i++){
int x=newnode(s[i]),las=0;
while(bd&&t[stk[bd]].rd<t[x].rd)pushup(stk[bd]),las=stk[bd--];
if(bd)t[stk[bd]].rson=x;
t[stk[++bd]=x].lson=las;
}
while(bd)pushup(stk[bd--]);
int a,b;
split(rt,tar,a,b);
rt=merge(merge(a,stk[1]),b);
}
void Delete(){
int len=read();
int a,b,c;
split(rt,tar,a,b);
split(b,len,b,c);
rt=merge(a,c),oldnode(b);
}
void Rotate(){
int len=read();
int a,b,c;
split(rt,tar,a,b);
split(b,len,b,c);
REV(b),rt=merge(merge(a,b),c);
}
void Move(){tar=read();}
void Next(){tar++;}
void Prev(){tar--;}
void leftmost(int x){
pushdown(x);
if(!t[x].lson){
putchar(t[x].ch);
if(t[x].ch!='\n')putchar('\n');
}else leftmost(t[x].lson);
}
/*
void iterate(int x){
if(!x)return;
pushdown(x);
iterate(t[x].lson);
putchar(t[x].ch);
iterate(t[x].rson);
}
*/
void Get(){
int a,b;
split(rt,tar,a,b);
leftmost(b);
rt=merge(a,b);
}
int main(){
n=read();
while(n--){
scanf("%s",s);
if(s[0]=='M')Move();
else if(s[0]=='I')Insert();
else if(s[0]=='D')Delete();
else if(s[0]=='R')Rotate();
else if(s[0]=='G')Get();
else if(s[0]=='P')Prev();
else if(s[0]=='N')Next();
// iterate(rt),putchar('\n');
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?