[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 做法分析 好多不同的做法都可以 ...
随机推荐
- MySQL系列:utf8_bin和utf8_general_ci编码的区别
MySQL中存在多种格式的utf8编码,其中最常见的两种为: utf8_bin utf8_general_ci utf8_bin将字符串中的每一个字符用二进制数据存储,区分大小写;utf8_gener ...
- JAVA Map的使用
学JAVA那么多天了,所以就不写那啥了,哈哈 Map 是一个很实用的东西,它查询的速度也是飞快的.还有很多好的地方, 至于好在哪里,我也说不清. 还是用代码来说吧: import java.util. ...
- CF385C Bear and Prime Numbers
思路: 需要对埃氏筛法的时间复杂度有正确的认识(O(nlog(log(n)))),我都以为肯定超时了,结果能过. 实现: #include <bits/stdc++.h> using na ...
- Junit测试集锦
Junit测试集锦 前言: 一个程序从设计很好的状态开始,随着新的功能不断地加入,程序逐渐地失去了原有的结构,最终变成了一团乱麻.所以在开发过程中,对于程序员来说,测试是非常重要的.言归正传,开始Ju ...
- JSP 错误处理方法
web.xml中配置error-page标签 1.WEB工程中打开 web.xml 文件
- knockout Observable Array(监控数组)
Observable Array(监控数组)的作用 列表操作是经常会遇到的一个场景,使用监控数组,你可以: 保存列表对象,并且使用Ko提供的丰富的API操作列表元素(支持内建js Array的方法,以 ...
- css广告弹窗满屏跑
window.onload=function(){ //广告滚动 var oneInner = $('#divid')[0]; //定时器 var a1a = setInterval(moves,10 ...
- hasOneOf # if (data.otherDescArr.some(_ => '7'.indexOf(_) > -1)) {
if (data.otherDescArr.some(_ => '7'.indexOf(_) > -1)) { export const hasOneOf = (targetarr, ar ...
- vs2010的资源视图中,对话框显示数字的解决方法之一
以上是不正常显示. 我这次遇到该问题的原因是资源名IDD_DLG_INTENSITY重复定义导致的, 所以在resource.h文件中去除重复定义就好了. 正常应该显示DD_XXX,如下图所示
- 尺取法 || emmmm
给定两个上升的数组,一个数组任取一个数,求两个数差的min 尺取法emm 也不知道对不对 #include <stdio.h> #include <stdlib.h> #def ...