[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 做法分析 好多不同的做法都可以 ...
 
随机推荐
- .net服务端生成二维码
			
mvc4 net4.0 1.引用附件的DLL文件 2.两个函数即可 #region 生成二维码 public ActionResult getQrCode() { using (var ms = ...
 - nodejs的mysql模块学习笔记(结合业务)
			
1. 包官网地址 https://www.npmjs.com/package/mysql#install https://www.oschina.net/translate/node-mysql-tu ...
 - windows下常用的一些shell命令
			
看的视频上都是linux系统的shell命令,和windows区别很多.所以整理了windows常用的一些shell命令. 注意:并不是每个都试验过,使用时还需自己验证下. 学system和os,su ...
 - jsapi4加载的首个图层的范围被默认作为地图范围,且不能修改的解决
			
在map加载的第一个图层的图层范围(fullExtent),会被默认设置为map的全图范围,且不能更改,从一般地图控件角度来说,应该有fullExtent属性,作为地图的全图范围,但很遗憾jsapi4 ...
 - laravel的scout包安装及laravel-es包安装
			
安装laravel/scout 作用:搜索驱动,可随时更换驱动,上层业务逻辑可不用改变 官网文档:https://laravel-china.org/docs/laravel/5.4/scout/12 ...
 - 移除sql数据所有链接用户
			
use master; go declare @temp nvarchar(20) declare myCurse cursor for select spid from sy ...
 - Angularjs 实现 $(document).ready()的两种方法
			
1.在controller里面利用$on或者$watch bookControllers.controller('bookctrl_test', ['$scope', '$routeParams', ...
 - IntelliJ IDEA openfire 使用IntelliJ IDEA 部署OPENFIRE 服务端
			
用MyEclipse部署OF的步骤,网上有很多,可以自行google,这里要记录的是用据说最好用的JAVA编辑器IntelliJ IDEA来部署OF服务端.试了好多下,终于成功了,记录下. 直接上图吧 ...
 - 禁用DRM
			
10G: alter system set "_gc_policy_time"=0 scope=spfile sid='*'; alter system set "_gc ...
 - zuul 整理
			
网关: 为了解决ip+端口的不友好性而产生.具有服务代理的功能nginx 功能: 1.验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求. 2.审查与监控: 在边缘位置追踪有意义数 ...