块状链表 poj2887
2011-05-27 11:28
155 查看
相当优秀的数据结构,splay可以做的sequence,它也可以做。
无论是翻转,插入,删除,最大值,最小值,区间和,第k大值,比t小数,第k个数,都可以做
该题只需插入和查询第k个数就可以了。
查询的时候要将长度小的块合并,插入的时候也可以做(但我懒得编了)。
1、查询:判断第x个块长度是否>k,若满足,则在该块第k个,否则k:=k-x.len,查询x.next;在此过程中顺便合并长度之和<sqrt(n)的块。
2、插入:若k>总长则插入在最后块,若块已满,则新建块,last指针后移;否则查询k号位置,若此块未满则直接插入,否则将此块从k处分裂,再插入。分裂的块可能会在之后合并,但短时间内会增加超出预估的块数,所以要多预设一部分块。
move函数很方便,不用担心超时,因为最多移sqrt(n)个,预设块可以开个栈,每次添块就从栈中取,合并块就将其中一个压入栈中。
这道题也可以用逆推的方式用线段树做,好像很少有人想到,思路由罗雨屏提供,详情可参见下一篇博文
无论是翻转,插入,删除,最大值,最小值,区间和,第k大值,比t小数,第k个数,都可以做
该题只需插入和查询第k个数就可以了。
查询的时候要将长度小的块合并,插入的时候也可以做(但我懒得编了)。
1、查询:判断第x个块长度是否>k,若满足,则在该块第k个,否则k:=k-x.len,查询x.next;在此过程中顺便合并长度之和<sqrt(n)的块。
2、插入:若k>总长则插入在最后块,若块已满,则新建块,last指针后移;否则查询k号位置,若此块未满则直接插入,否则将此块从k处分裂,再插入。分裂的块可能会在之后合并,但短时间内会增加超出预估的块数,所以要多预设一部分块。
move函数很方便,不用担心超时,因为最多移sqrt(n)个,预设块可以开个栈,每次添块就从栈中取,合并块就将其中一个压入栈中。
这道题也可以用逆推的方式用线段树做,好像很少有人想到,思路由罗雨屏提供,详情可参见下一篇博文
const maxl=1000; type block=record len,next:longint; s:array[1..1500]of char; end; var a:array[0..4001]of block; n,last,he,ans,new,top,head,l:longint; st:array[1..500000]of longint; procedure conect(x,y:longint); begin move(a[y].s[1],a[x].s[a[x].len+1],a[y].len); a[x].len:=a[x].len+a[y].len;a[x].next:=a[y].next; fillchar(a[y],sizeof(a[y]),0); inc(top);st[top]:=y end; function find(x:longint):longint; begin he:=head; while a[he].len<x do begin while a[he].len+a[a[he].next].len<maxl do conect(he,a[he].next); if a[he].len>=x then break else x:=x-a[he].len; he:=a[he].next end; find:=x end; procedure inset(x:char;k:longint); var ne:longint; begin inc(l); if k>l-1 then begin if a[last].len<maxl then begin inc(a[last].len);a[last].s[a[last].len]:=x; exit end; inc(new);ne:=st[new]; a[last].next:=ne;last:=ne; inc(a[ne].len);a[ne].s[a[ne].len]:=x; exit end; ans:=find(k); if a[he].len<maxl then begin with a[he] do begin move(s[ans],s[ans+1],len-ans+1); s[ans]:=x;inc(len) end; exit end; inc(new);ne:=st[new]; a[ne].next:=a[he].next;a[he].next:=ne; move(a[he].s[ans],a[ne].s[1],a[he].len-ans+1); a[ne].len:=a[he].len-ans+1;a[he].len:=ans;a[he].s[ans]:=x; if last=he then last:=ne end; procedure init; var i,ne:longint; x,y,z,p:char; k:longint; begin for i:=1 to 4001 do st[i]:=i;top:=4001; last:=0;new:=0;a[0].len:=maxl;head:=1;l:=0; while not(seekeoln) do begin read(x); with a[last] do if len<maxl-1 then begin inc(len);s[len]:=x;inc(l) end else begin inc(new);ne:=st[new];a[last].next:=ne; last:=ne;inc(a[ne].len);a[ne].s[a[ne].len]:=x;inc(l) end end; readln; readln(n); for i:=1 to n do begin read(x,y); if x='I' then begin readln(z,p,k); inset(z,k) end else begin readln(k); ans:=find(k); writeln(a[he].s[ans]) end end end; begin assign(input,'2887.in');reset(input); init; close(input) end.
相关文章推荐
- POJ2887【块状链表】
- POJ2887 Big String 块状链表
- 【POJ2887】【块状链表】Big String
- poj2887 Big String(块状链表)
- 【POJ2887】【块状链表】Big String
- POJ2887(块状链表)
- 【BZOJ3295】【块状链表+树状数组】动态逆序对
- POJ 2887 Big String(块状链表)
- 块状链表之代码分析
- 初识块状数组/块状链表(讲解+ 例题)
- bzoj3337 块状链表的各种操作
- poj 3468 块状链表 区间修改+区间查询
- 块状链表[ext/rope]
- 数据结构之块状链表
- poj 2828 块状链表 OR 线段树 OR 树状数组
- 【BZOJ2120】【块状链表】数颜色
- 块状链表(附NOI 2003 Editor,POJ 2131 Key Insertion)
- POJ2887 Big String(块状数组)
- BZOJ 1507([NOI2003]Editor-块状链表)
- 块状链表及其实现