洛谷P4008 [NOI2003] 文本编辑器 题解 块状链表
题目链接:https://www.luogu.com.cn/problem/P4008
思路和题解参考自:https://www.luogu.com.cn/article/jsj8kne5
Find 函数很好用!赞!
区别:
- 我是自己手写的双向链表;
- 由于我的操作不会出现大于 blo(blo 是设定的最大分块大小)的分块,所以不会出现块大小 大于 blo 的情况,所以 Update 函数中不会切分块(只需合并块)
另外,要 注意一些细节。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5, blo = 2500;
int T, l[maxn], r[maxn], idx, pos;
vector<char> vec[maxn];
char op[15];
void ins(int x, int y) {
int z = r[x];
r[x] = y, l[y] = x;
r[y] = z, l[z] = y;
}
int Find(int &pos) {
for (int x = 0; ; x = r[x]) {
if (pos <= vec[x].size())
return x;
pos -= vec[x].size();
}
assert(1 == 0);
}
void Split(int x, int k) {
assert(k <= vec[x].size());
if (k == vec[x].size())
return;
int y = ++idx;
vec[y].assign(vec[x].begin() + k, vec[x].end());
vec[x].erase(vec[x].begin() + k, vec[x].end());
ins(x, y);
}
void Update() {
for (int x = r[0]; x; x = r[x]) {
int y = r[x];
if (y && vec[x].size() + vec[y].size() <= blo) {
int z = r[y];
vec[x].insert(vec[x].end(), vec[y].begin(), vec[y].end());
vec[y].clear();
r[x] = z, l[z] = x;
}
}
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%s", op);
if (op[0] == 'M') { // Move k
scanf("%d", &pos);
}
else if (op[0] == 'I') { // Insert n s
int n, p = pos; char c;
scanf("%d", &n);
int x = Find(p);
Split(x, p);
int y = ++idx;
int sz = 0;
while (n--) {
c = getchar();
while (c < 32 || c > 126)
c = getchar();
vec[y].push_back(c);
if (++sz == blo && n) {
ins(x, y);
x = r[x]; /** 这句话也很重要! **/
assert(x == y);
y = ++idx;
sz = 0;
}
}
if (sz)
ins(x, y);
Update();
}
else if (op[0] == 'D') { // Delete n
int n;
scanf("%d", &n);
int p1 = pos, p2 = pos + n;
int x = Find(p1), y = Find(p2);
Split(y, p2); /*****************************/
int z = r[y]; /** 注意这三行的顺序!!! **/
Split(x, p1); /*****************************/
r[x] = z, l[z] = x;
Update();
}
else if (op[0] == 'G') { // Get n
int n;
scanf("%d", &n);
int p1 = pos, p2 = pos + n;
int x = Find(p1), y = Find(p2);
for (int i = x; ; i = r[i]) {
int a = 0, b = vec[i].size();
if (i == x) a = p1;
if (i == y) b = p2;
for (int j = a; j < b; j++)
putchar(vec[i][j]);
if (i == y)
break;
}
putchar('\n');
}
else if (op[0] == 'P') { // Prev
pos--;
}
else { // Next
pos++;
}
}
return 0;
}
浙公网安备 33010602011771号