[NOI2003]Editor(块状链表)
看了看块状链表,就是数组和链表的合体。
看上去好高大尚,思想也很简单。
但是发现代码量也不是很小,而且代码理解起来也是费尽得很,倒不如splay用起来顺手。
在加上适用范围貌似不是特别广,所以只把模板贴在这,只当了解思想,暂时先不使用。(也不会用啊)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std; const int N=<<;
const int blocksize=;
const int blocknum=N/blocksize*; int T,_;
int cur;
char str[],opt[];
queue <int> q;
struct node
{
char data[blocksize+];
int len,nxt;
}a[blocknum+]; void init()
{
for (int i=;i<=blocknum;++i) q.push(i);
a[].len=; a[].nxt=-;
}
void read(int len)
{
int i=-;
while (i<len-)
{
i++;
char c=getchar();
str[i]=c;
if (c<||c>) i--;
}
}
//新开一个块的节点
int newnode()
{
int temp=q.front(); q.pop();
return temp;
}
//回收块的节点
void delnode(int t)
{
q.push(t);
}
//找到pos所在的块,并使pos表示在当前块中的位置
void find(int &pos,int &now)
{
for (now=;a[now].nxt!=-&&pos>a[now].len;now=a[now].nxt)
pos-=a[now].len;
}
//将新快赋值
void fillnode(int pos,int n,char data[],int nxt)
{
a[pos].nxt=nxt; a[pos].len=n;
memcpy(a[pos].data,data,n);
}
//将块pos在p位置前后分开,变成两个块
void split(int pos,int p)
{
if (a[pos].len==p) return;
int t=newnode();
fillnode(t,a[pos].len-p,a[pos].data+p,a[pos].nxt);
a[pos].nxt=t; a[pos].len=p;
}
//把碎块合并
void maintain(int pos)
{
int t;
for (;pos!=-;pos=a[pos].nxt)
for (t=a[pos].nxt;t!=-&&a[pos].len+a[t].len<blocksize;t=a[t].nxt)
{
memcpy(a[pos].data+a[pos].len,a[t].data,a[t].len);
a[pos].len+=a[t].len; a[pos].nxt=a[t].nxt; delnode(t);
}
}
//在光标pos处插入长度为n的str
void insert(int pos,int n)
{
int now,i,t;
//now表示光标所在的块,pos表示光标在这个块中的位置
find(pos,now);
split(now,pos);
for (i=;i+blocksize<=n;i+=blocksize)
{
t=newnode();
fillnode(t,blocksize,str+i,a[now].nxt);
a[now].nxt=t;
now=t;
}
if (i<n)
{
t=newnode();
fillnode(t,n-i,str+i,a[now].nxt);
a[now].nxt=t;
}
maintain(now);
}
//从光标pos开始删除长度为n的字符串
void del(int pos,int n)
{
int i,now,t;
//now表示光标所在的块,pos表示光标在这个块中的位置
find(pos,now);
split(now,pos);
//找到删除的末尾的点所处的块
for (i=a[now].nxt;i!=-&&n>a[i].len;i=a[i].nxt)
n-=a[i].len;
split(i,n); i=a[i].nxt;
for (t=a[now].nxt;t!=i;t=a[now].nxt)
a[now].nxt=a[t].nxt,delnode(t);
maintain(now);
}
//从pos这个位置开始输出长度为n的字符串
void get(int pos,int n)
{
int i,now,t;
find(pos,now);
i=min(n,a[now].len-pos);
memcpy(str,a[now].data+pos,i);
for (t=a[now].nxt;t!=-&&i+a[t].len<=n;t=a[t].nxt)
{
memcpy(str+i,a[t].data,a[t].len);
i+=a[t].len;
}
if (i<n&&t!=-) memcpy(str+i,a[t].data,n-i);
str[n]=;
}
int main()
{
init();
scanf("%d",&T);
while (T--)
{
scanf("%s",opt);
if (opt[]=='M') scanf("%d",&cur);//改变光标的位置
if (opt[]=='I')//插入一段区间
{
scanf("%d",&_);
read(_);
insert(cur,_);
}
if (opt[]=='P') cur--;//光标左移
if (opt[]=='N') cur++;//光标右移
if (opt[]=='D')//删除一段区间
{
scanf("%d",&_);
del(cur,_);
}
if (opt[]=='G')//输出一段区间
{
scanf("%d",&_);
get(cur,_);
puts(str);
}
}
}
[NOI2003]Editor(块状链表)的更多相关文章
- 【BZOJ-1507】Editor 块状链表
1507: [NOI2003]Editor Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 3397 Solved: 1360[Submit][Stat ...
- 【BZOJ 1507】【NOI 2003】&【Tyvj P2388】Editor 块状链表模板题
2016-06-18 当时关于块状链表的想法是错误的,之前维护的是一个动态的$\sqrt{n}$,所以常数巨大,今天才知道原因TwT,请不要参照这个程序为模板!!! 模板题水啊水~~~ 第一次写块状链 ...
- 洛谷.4008.[NOI2003]editor文本编辑器(块状链表)
题目链接 st(n)表示sqrt(n) 为使块状链表不会退化,通常将每块的大小S维持在[st(n)/2,2st(n)]中,这样块数C也一定[st(n)/2,2st(n)]中 在此使用另一种方法(方便) ...
- 1507: [NOI2003]Editor(块状链表)
1507: [NOI2003]Editor Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 4157 Solved: 1677[Submit][Stat ...
- BZOJ 1507 Editor(块状链表)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1507 题意:一个文本编辑器,模拟以下操作: 思路:块状链表的主要操作: (1)find( ...
- luogu P4008 [NOI2003]文本编辑器 splay 块状链表
LINK:文本编辑器 这个东西感觉块状链表写细节挺多 (块状链表本来就难写 解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n). 这样插入删除的时候直接暴 ...
- 1507: [NOI2003]Editor
1507: [NOI2003]Editor Time Limit: 5 Sec Memory Limit: 162 MB Submit: 3535 Solved: 1435 [Submit][St ...
- ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)
题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...
- POJ 2887 Big String(块状链表)
题目大意 给一个字符串,长度不超过 106,有两种操作: 1. 在第 i 个字符的前面添加一个字符 ch 2. 查询第 k 个位置是什么字符 操作的总数不超过 2000 做法分析 好多不同的做法都可以 ...
随机推荐
- Windows下Apache应用环境塔建安全设置(目录权限设置)
目的:为Apache,php配置受限制的用户权限.保护系统安全.需要的朋友可以参考下. 环境配置情况: apache安装目录:d:\www-s\apache php目录:d:\www-s\php5 m ...
- AJPFX辨析Java中运算符 ++ 和 += 的区别
我们都知道Java中 ++ 和 +=1 都是把数字增加一后,把值赋给左边,那二者有什么区别呢? i+=1 运行的底层Heap申请一个区域存放i,在数据区域开劈一个区域存放1,2个内存段被数据被送入到 ...
- return false 的其中一种用法
return false 的具体是做什么的在这里就不多说了,因为我觉得我形容不明白.....避免大家弄混乱,就不给大家添麻烦了~~ 直接上例子: 1.先看看下面一段代码,指出其中的错误所在: //点击 ...
- CF989C A Mist of Florescence
思路: 有趣的构造题. 实现: #include <bits/stdc++.h> using namespace std; ][]; void fillin(int x, int y, c ...
- 字符串、数组、json
一.字符串 string 1.字符串的定义: (1).var s="haha"; (2).var s=new string ("hello") 对象形式定义 2 ...
- 事件对象(示例、封装函数EventUtil())
事件对象 什么是事件对象? 在触发DOM上的事件时都会产生一个对象. 事件对象event 1.DOM中的事件对象 (1)\type属性用于获取事件类型 (2)\target属性用于获取事件目标 (3) ...
- 微信小程序 开放能力学习
1. 用户信息小程序登录使用微信的个人信息快速搭建用户体系,登录逻辑:小程序向微信获取code 给服务端生成用户. 说明1. 小程序端调用 wx.login() 获取临时登录凭证 code,并传到服务 ...
- Javaweb学习笔记5—Cookie&Session
今天来讲javaweb的第五阶段学习. Cookie和Session同样是web开发常用到的地方. 老规矩,首先先用一张思维导图来展现今天的博客内容. ps:我的思维是用的xMind画的,如果你对我的 ...
- Android(java)学习笔记175:Android进程间通讯(IPC)之AIDL
一.IPC inter process communication 进程间通讯 二.AIDL android interface defination language 安卓接口定义语言 满 ...
- swift Equatable 的缺省实现
Starting from Swift 4.1, all you have to is to conform to the Equatable protocol without the need of ...