POJ 2887 Big String(块状链表)

 

题目大意

 

给一个字符串,长度不超过 106,有两种操作:

  1. 在第 i 个字符的前面添加一个字符 ch

  2. 查询第 k 个位置是什么字符

操作的总数不超过 2000

 

做法分析

 

好多不同的做法都可以搞

人生第一个块状链表,记录下

块状链表的思想其实挺简单的,传统的链表每个节点只记录一个字符,块状链表的每个节点记录的是 sqrt(n) 个信息,一个长度为 n 的字符串就被分成了 sqrt(n) 个。这样,查询和插入字符的操作就变成了 sqrt(n)级别的了,对于这题 2000 个操作来讲,时间复杂度还能忍受

这题只有插入和查询操作,所以写起来非常简单

不过我不喜欢使用指针搞来稿去的,所以写的数组形式的

 

参考代码

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 
 7 const int N=2000, LEN=2000;
 8 
 9 struct Block_List {
10     struct Node {
11         char buff[LEN];
12         int next, Size;
13         void init() {
14             memset(buff, 0, sizeof buff);
15             next=-1, Size=0;
16         }
17     } List[N];
18     int head, tot;
19 
20     void init(char S[]) {
21         head=tot=0;
22         List[tot++].init();
23         for(int i=0, cur=head; S[i]; cur=List[cur].next) {
24             for(int j=0; j<LEN && S[i]; j++, i++) {
25                 List[cur].buff[j]=S[i];
26                 List[cur].Size++;
27             }
28             if(S[i]) {
29                 List[tot].init();
30                 List[cur].next=tot++;
31             }
32         }
33         for(int cur=head; cur!=-1; cur=List[cur].next)
34             if(List[cur].Size==LEN) Split(cur);
35     }
36 
37     void Split(int id) {
38         List[tot].init();
39         for(int i=LEN/2; i<LEN; i++) {
40             List[tot].buff[i-LEN/2]=List[id].buff[i];
41             List[tot].Size++;
42             List[id].buff[i]=0;
43             List[id].Size--;
44         }
45         List[tot].next=List[id].next;
46         List[id].next=tot++;
47     }
48 
49     void Insert(int pos, char val) {
50         int cur=head;
51         while(pos>List[cur].Size && List[cur].next!=-1) {
52             pos-=List[cur].Size;
53             cur=List[cur].next;
54         }
55         if(pos>=List[cur].Size) List[cur].buff[List[cur].Size]=val;
56         else {
57             for(int i=List[cur].Size; i>pos; i--) List[cur].buff[i]=List[cur].buff[i-1];
58             List[cur].buff[pos]=val;
59         }
60         List[cur].Size++;
61         if(List[cur].Size==LEN) Split(cur);
62     }
63 
64     char Find(int pos) {
65         int cur=head;
66         while(pos>List[cur].Size) pos-=List[cur].Size, cur=List[cur].next;
67         return List[cur].buff[pos-1];
68     }
69 };
70 
71 Block_List hehe;
72 char buff[1000006], S[2];
73 int n;
74 
75 int main() {
76 //    freopen("in", "r", stdin);
77     scanf("%s", buff);
78     hehe.init(buff);
79     scanf("%d", &n);
80     for(int i=0, pos; i<n; i++) {
81         scanf("%s", buff);
82         if(buff[0]=='I') {
83             scanf("%s%d", S, &pos);
84             hehe.Insert(pos-1, S[0]);
85         }
86         else {
87             scanf("%d", &pos);
88             printf("%c\n", hehe.Find(pos));
89         }
90     }
91     return 0;
92 }
POJ 2887

 

题目链接 & AC 通道

 

POJ 2887 Big String

 

 

 

转载于:https://www.cnblogs.com/zhj5chengfeng/p/3267659.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值