胡闹 文本编辑器

题目大意

你要支持以下几种操作:

  • $I$ $x$ $a$ : 在第$x$个字符后面插入字符$a$

  • $D$ $x$ $y$:删除从$x$到$y$的这一段

  • $C$ $x$ $y$ $z$ :复制从$x$到$y$这一段,粘贴到第$z$个字符后面

  • $P$ $x$ $y$ $z$ :打印$x$次修改操作之前,从$y$到$z$这一段。其中,$x$不超过一个给定的数$M$。

保证输入的所有数在$int$范围内。

数据规模与约定

对于$40%$的数据,总操作数和任意时刻字符串的长度在$1000$以内。

对于$100%$的数据,字符串的内容仅包含大小写字母和数字,初始字符串的长度和操作数不超过$100000$ ,$M\le 1000$ 。

解析

就是说用一个$fhq​$来维护

然后可持久化一下,就是$split​$的时候新建结点。

有以下卡常技巧:

  1. 按秩合并(玄学)
  2. $inline,register​$
  3. 输出的时候不中序遍历,一个一个往下找(玄学)
  4. 少传址
  5. 用返回$int$的$merge$而不用传址的$merge$
  6. srand(咕咕咕)

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#define REP(i, s, e) for (int i = s; i <= e ;i++)

#include <bits/stdc++.h>

using namespace std;
const int maxnode = 8e7 + 10;

struct node
{
int l, r, s;
char c;
}t[maxnode];
int cur;
inline int newnode(char c)
{
++cur;
t[cur].l = t[cur].r = 0;
t[cur].c = c;t[cur].s = 1;
return cur;
}
inline int copy(int x)
{
t[++cur] = t[x];
return cur;
}
inline void pushup(int x) {t[x].s = t[t[x].l].s + t[t[x].r].s + 1;}
inline void split(int x, int &a, int &b, int siz)
{
if (!x) a = b = 0;
else
if (t[t[x].l].s >= siz)
{
b = copy(x);
split(t[b].l, a, t[b].l, siz);
pushup(b);
}
else
{
a = copy(x);
split(t[a].r, t[a].r, b, siz - t[t[x].l].s - 1);
pushup(a);
}
}
inline int merge(int a, int b)
{
if (!a || !b) return a ^ b;
register int z;
if (t[a].s < t[b].s) z = b, t[z].l = merge(a, t[z].l);
else z = a, t[z].r = merge(t[z].r, b);
pushup(z);
return z;
}

int rt[100000 + 10], now;

int n, m;
char c;
inline int read()
{
c = getchar();
while (!isdigit(c)) c = getchar();
int ans(0);
while (isdigit(c)) ans = (ans << 1) + (ans << 3) + (c & 15), c = getchar();
return ans;
}
inline void output(int _)
{
if (!_) return;
output(t[_].l);
putchar(t[_].c);
output(t[_].r);
}
char ssr[10], s[100000 + 10];
inline int build(int l, int r)
{
if (l > r) return 0;
int mid = l + r >> 1;
int p = newnode(s[mid]);
t[p].l = build(l, mid - 1);
t[p].r = build(mid + 1, r);
pushup(p);
return p;
}
inline char query(int p, int k)
{
while (1)
{
if (t[t[p].l].s + 1 == k) return t[p].c;
if (t[t[p].l].s + 1 < k) k -= t[t[p].l].s + 1, p = t[p].r;
else p = t[p].l;
}
}
int pos, l, r, ccc, x, y, z;

int main()
{
#ifndef ONLINE_JUDGE
freopen("B.in", "r", stdin);
freopen("B.out", "w", stdout);
#endif
t[0] = (node){0,0,0,'\0'};
read();
scanf("%s", s + 1);
rt[0] = build(1, strlen(s + 1));
while (scanf("%s", ssr) != EOF)
if (ssr[0] == 'I')
{
pos = read();
scanf("%s", ssr);
++now;
x = y = 0;
split(rt[now-1], x, y, pos);
rt[now] = merge(merge(x, newnode(ssr[0])), y);
}
else if (ssr[0] == 'D')
{
l = read(), r = read();
++now;
x = y = z = 0;
split(rt[now-1], x, y, l - 1);
split(y, y, z, r - l + 1);
rt[now] = merge(x, z);
}
else if (ssr[0] == 'C')
{
l = read(), r = read(), pos = read();
++now;
x = y = z = 0;
split(rt[now-1], x, y, l - 1);
split(y, y, z, r - l + 1);
split(rt[now-1], x, z, pos);
rt[now] = merge(merge(x, y), z);
}
else
{
ccc = read(), l = read(), r = read();
REP(i, l, r) putchar(query(rt[now-ccc], i));
putchar(10);
}
return 0;
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×