SHOW:
|
|
- or go back to the newest paste.
1 | #include<bits/stdc++.h> | |
2 | ||
3 | #define endl "\n" | |
4 | using namespace std; | |
5 | using ll = long long; | |
6 | using ld = long double; | |
7 | using pii = pair<int, int>; | |
8 | ||
9 | constexpr int N = 1e6 + 5; | |
10 | ||
11 | constexpr ll mod = 1e9 + 9; | |
12 | ||
13 | int n, l, r, type, v; | |
14 | string init; | |
15 | ||
16 | ll deg[N]; | |
17 | ||
18 | ll mul(ll l, ll r){ | |
19 | return (l * r) % mod; | |
20 | } | |
21 | ||
22 | ll sum(ll l, ll r){ | |
23 | return (l + r) % mod; | |
24 | } | |
25 | ||
26 | struct Treap{ | |
27 | struct Node{ | |
28 | bool isrev; | |
29 | char val; | |
30 | int sz; | |
31 | int pri; | |
32 | Node *l, *r; | |
33 | ll hash; | |
34 | ll revhash; | |
35 | Node(char a = '0', Node *le = nullptr, Node *ri = nullptr) : | |
36 | val(a), pri((rand() << 16) + rand()), sz(1), | |
37 | hash(a - 'a' + 1), revhash(a - 'a' + 1), | |
38 | l(le), r(ri) {}; | |
39 | }; | |
40 | ||
41 | using pN = Node*; | |
42 | using pNN = pair<pN, pN>; | |
43 | ||
44 | Node buff[N]; | |
45 | pN root = nullptr; | |
46 | int st = 0; | |
47 | ||
48 | pN newN(char val){ | |
49 | buff[st] = Node(val); | |
50 | return &buff[st++]; | |
51 | } | |
52 | ||
53 | int getsz(pN v){ | |
54 | return v == nullptr ? 0 : v -> sz; | |
55 | } | |
56 | ||
57 | ll gethash(pN v){ | |
58 | return v == nullptr ? 0 : v -> hash; | |
59 | } | |
60 | ||
61 | ll getrevhash(pN v){ | |
62 | return v == nullptr ? 0 : v -> hash; | |
63 | } | |
64 | ||
65 | void recalc(pN v){ | |
66 | v -> sz = getsz(v -> l) + getsz(v -> r) + 1; | |
67 | v -> hash = sum(sum(gethash(v -> l), mul(gethash(v -> r), | |
68 | deg[getsz(v -> l) + 1])), mul((v -> val - 'a' + 1ll), deg[getsz(v -> l)])); | |
69 | v -> revhash = sum(sum(getrevhash(v -> r), mul(getrevhash(v -> l), | |
70 | deg[getsz(v -> r) + 1])), mul((v -> val - 'a' + 1ll), deg[getsz(v -> r)])); | |
71 | return; | |
72 | } | |
73 | ||
74 | pNN split(pN v, int k){ | |
75 | if (k == 0) | |
76 | return {nullptr, v}; | |
77 | push(v); | |
78 | if (getsz(v -> l) >= k){ | |
79 | auto p = split(v -> l, k); | |
80 | v -> l = p.second; | |
81 | recalc(v); | |
82 | return {p.first, v}; | |
83 | } | |
84 | else { | |
85 | auto p = split(v -> r, k - getsz(v -> l) - 1); | |
86 | v -> r = p.first; | |
87 | recalc(v); | |
88 | return {v, p.second}; | |
89 | } | |
90 | } | |
91 | ||
92 | pN merge(pN l, pN r){ | |
93 | if (l == nullptr) | |
94 | return r; | |
95 | if (r == nullptr) | |
96 | return l; | |
97 | if (l -> pri < r -> pri){ | |
98 | push(l); | |
99 | l -> r = merge(l -> r, r); | |
100 | recalc(l); | |
101 | return l; | |
102 | } | |
103 | else { | |
104 | push(r); | |
105 | r -> l = merge(l, r -> l); | |
106 | recalc(r); | |
107 | return r; | |
108 | } | |
109 | } | |
110 | ||
111 | void insert(int k, char val){ | |
112 | auto p1 = split(root, k); | |
113 | auto v = newN(val); | |
114 | root = merge(merge(p1.first, v), p1.second); | |
115 | return; | |
116 | } | |
117 | ||
118 | void reverse(pN v){ | |
119 | if (v == nullptr) | |
120 | return; | |
121 | v -> isrev ^= 1; | |
122 | swap(v -> hash, v -> revhash); | |
123 | swap(v -> l, v -> r); | |
124 | } | |
125 | ||
126 | void push(pN v){ | |
127 | if (v == nullptr) | |
128 | return; | |
129 | if (v -> isrev){ | |
130 | reverse(v -> l); | |
131 | reverse(v -> r); | |
132 | v -> isrev = 0; | |
133 | swap(v -> hash, v -> revhash); | |
134 | } | |
135 | return; | |
136 | } | |
137 | ||
138 | void rev(int l, int r){ | |
139 | auto p1 = split(root, r); | |
140 | auto p2 = split(p1.first, l - 1); | |
141 | reverse(p2.second); | |
142 | root = merge(merge(p2.first, p2.second), p1.second); | |
143 | return; | |
144 | } | |
145 | ||
146 | void clear(){ | |
147 | st = 0; | |
148 | root = nullptr; | |
149 | } | |
150 | ||
151 | } tr1, tr2; // tr2 is copy of tr1 (only difference is priority) | |
152 | ||
153 | bool check(int len, int l, int r){ | |
154 | auto p1 = tr1.split(tr1.root, l - 1); | |
155 | auto p2 = tr2.split(tr2.root, r - 1); | |
156 | auto p3 = tr1.split(p1.second, len); | |
157 | auto p4 = tr2.split(p2.second, len); | |
158 | bool ans = (tr1.gethash(p3.first) == tr2.gethash(p4.first)); | |
159 | tr1.root = tr1.merge(p1.first, tr1.merge(p3.first, p3.second)); | |
160 | tr2.root = tr2.merge(p2.first, tr2.merge(p4.first, p4.second)); | |
161 | return ans; | |
162 | } | |
163 | ||
164 | int findk(int ql, int qr){ | |
165 | int l = 0, r = tr1.getsz(tr1.root) - qr + 1, mid, ans = 0; | |
166 | while (l <= r){ | |
167 | mid = (l + r) >> 1; | |
168 | if (check(mid, ql, qr)) | |
169 | ans = mid, l = mid + 1; | |
170 | else r = mid - 1; | |
171 | } | |
172 | return ans; | |
173 | } | |
174 | ||
175 | ||
176 | void Solve(){ | |
177 | deg[0] = 1ll; | |
178 | for (int i = 1; i < N; i++) | |
179 | deg[i] = mul(deg[i - 1], 31ll); | |
180 | cin >> init; | |
181 | for (int i = 0; i < init.size(); i++){ | |
182 | tr1.insert(i, init[i]); | |
183 | tr2.insert(i, init[i]); | |
184 | } | |
185 | cin >> n; | |
186 | while (n--){ | |
187 | cin >> type >> l >> r; | |
188 | if (type == 1){ | |
189 | tr1.rev(l, r); | |
190 | tr2.rev(l, r); | |
191 | } | |
192 | else | |
193 | cout << findk(l, r) << endl; | |
194 | } | |
195 | } | |
196 | ||
197 | int main(){ | |
198 | ios::sync_with_stdio(false); | |
199 | cin.tie(nullptr); | |
200 | cout.tie(nullptr); | |
201 | Solve(); | |
202 | return 0; | |
203 | } |