QwQ和01串

Description

QwQ是所有`01`串的控制者,但因为`0`是虚的,`1`才是实的,所以QwQ的遥控器只能控制`1`而不能直接控制`0`。

不幸的是,QwQ的遥控器坏了,控制力有所衰减,只能必须是连续的三个1才能被QwQ所控制。

对于一个01可以对它实施这样一个操作:选择中三个连续的1,把这三位向前或向后移动任意多位。

比如说这样: 001110110010 000111110010

或者这样:001110110010 111000110010

如果串可以通过QwQ的若干次操作得到,QwQ就认为相等的。

有一天QwQ终于发现了宇宙的本质就是一个长度为01但大部分人并不能理解这个神奇的宇宙,于是他们向01串的造物主QwQ问了个问题,每个问题的形式如下:中的第位到第位所组成的子串是否等于中的第位到第位所组成的子串?

Input

第一行输入2个正整数,表示宇宙串的长度和询问次数

第二行输入1个长度为01串表示QwQ对整个宇宙的理解。

接下来qq行每行四个正整数,表示每个询问。

题目保证对于每个询问,,

Output

对于每个询问,输出一行`Yes`或`No`。
一开始的做法是先求前缀和然后找0的位置并用辅助数组jl[]记录当前k字符上一'0'的索引,若k字符为'0'则记录其本身的索引

然后7.8.9的测试点就爆掉了

最后AC的做法是用BKDR_hash来回应问询,加上快读到70ms

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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#include <bits/stdc++.h>

#define LL long long
#define f(i, a, b) for (int i = a; i <= b; i++)
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "w", stdout)

const LL B = 13331;
const LL M = 33951943;
const LL BA = 233;

char s[200087];
LL sum[200087], jl[200087], rank[200087], bk[200087], hash_at[200087]; //back to index
int n, q, aa, bb, cc, dd;

typedef unsigned long long ull;
ull hashs[200087], po[200087];
struct FastIO
{
static const int S = 5 << 20; //MB
int wpos;
char wbuf[S];
FastIO() : wpos(0) {}
inline int xchar()
{
static char buf[S];
static int len = 0, pos = 0;
if (pos == len)
pos = 0, len = fread(buf, 1, S, stdin);
if (pos == len)
return -1;
return buf[pos++];
}
inline int xint()
{
int s = 1, c = xchar(), x = 0;
while (c <= 32)
c = xchar();
if (c == '-')
s = -1, c = xchar();
for (; '0' <= c && c <= '9'; c = xchar())
x = x * 10 + c - '0';
return x * s;
}
inline void xstring(char *s)
{
int c = xchar();
while (c <= 32)
c = xchar();
for (; c > 32; c = xchar())
*s++ = c;
*s = 0;
}
inline void wll(LL x)
{
if (x < 0)
wchar('-'), x = -x;

char s[30];
int n = 0;
while (x || !n)
s[n++] = '0' + x % 10, x /= 10;
while (n--)
wchar(s[n]);
}
inline void wchar(int x)
{
if (wpos == S)
fwrite(wbuf, 1, S, stdout), wpos = 0;
wbuf[wpos++] = x;
}
inline void wstring(const char *s)
{
while (*s)
wchar(*s++);
}
~FastIO()
{
if (wpos)
fwrite(wbuf, 1, wpos, stdout), wpos = 0;
}
} io;

LL quikpower(LL b)
{
LL ans = 1, base = BA;
while (b > 0)
{
if (b & 1)
{
ans *= base;
ans %= M;
}
base *= base;
base %= M;
b >>= 1;
}
return ans;
}

void sums()
{
sum[1] = s[0] - '0';
jl[1] = 1;
f(i, 2, n)
{
if (s[i - 1] == '0')
jl[i] = i;
else
jl[i] = jl[i - 1];
sum[i] = sum[i - 1] + s[i - 1] - '0';
}
int sum_0 = n - sum[n], judge = n; //sum_0::0的个数
//io.wll(sum_0);
for (int cnt = sum_0; cnt > 0; cnt--)
{
bk[cnt] = jl[judge]; //第cnt个0的index
rank[jl[judge]] = cnt; //0-index to cnt
judge = jl[judge] - 1;
}
}

void hash_init()
{
int sum_0 = n - sum[n];
po[0] = 1;
po[1] = B;
hashs[bk[1]] = (sum[bk[1]] - sum[0]) % 3; //第一个0
hash_at[bk[1]] = (sum[bk[1]] - sum[0]) % 3;
for (int k = 2; k <= sum_0; k++)
{
hashs[bk[k]] = ((sum[bk[k]] - sum[bk[k - 1]]) % 3 + hashs[bk[k - 1]] * B);
hash_at[bk[k]] = ((sum[bk[k]] - sum[bk[k - 1]]) % 3 + hash_at[bk[k - 1]] * BA) % M;
po[k] = po[k - 1] * B;
}
}

LL gethash2(int l, int r)
{
if (rank[l] == 1)
return hash_at[r];
return (hash_at[r] + M - hash_at[bk[rank[l] - 1]] * quikpower(rank[r] - rank[l] + 1) % M) % M;
}

LL gethash(int l, int r)
{
if (rank[l] == 1)
return hashs[r];
return (hashs[r] - hashs[bk[rank[l] - 1]] * po[rank[r] - rank[l] + 1]);
}

int check2(int a, int b, int c, int d)
{
if (sum[b] - sum[a - 1] != sum[d] - sum[c - 1])
{
io.wstring("No\n");
return 0;
}
int x = jl[b], y = jl[d];
while (x >= a && y >= c)
{
if (abs(sum[b] - sum[x] - sum[d] + sum[y]) % 3)
{
io.wstring("No\n");
return 0;
}
else
{
x = jl[x - 1];
y = jl[y - 1];
}
}
io.wstring("Yes\n");
return 0;
}

void check(int a, int b, int c, int d)
{
if (b - a + 1 - sum[b] + sum[a - 1] < 2)
{
check2(a, b, c, d);
return;
}
if (sum[b] - sum[a - 1] != sum[d] - sum[c - 1] || ((abs(sum[b] - sum[jl[b]] - sum[d] + sum[jl[d]]) % 3) && jl[b] >= a && jl[d] >= c))
{
io.wstring("No\n");
return;
}
int star = a;
while (s[star - 1] == '1')
{
star += 1;
}
int le1 = sum[star] - sum[a - 1];
ull ha1 = gethash(bk[rank[star] + 1], jl[b]);
LL ha1_a = gethash2(bk[rank[star] + 1], jl[b]);
star = c;
while (s[star - 1] == '1')
{
star += 1;
}
int le2 = sum[star] - sum[c - 1];
ull ha2 = gethash(bk[rank[star] + 1], jl[d]);
LL ha2_a = gethash2(bk[rank[star] + 1], jl[d]);
if (ha1 == ha2 && abs(le1 - le2) % 3 == 0 && ha1_a == ha2_a)
io.wstring("Yes\n");
else
io.wstring("No\n");
}
int main()
{
IN;
OUT;
n = io.xint();
q = io.xint();
io.xstring(s);
sums();
hash_init();
f(i, 1, q)
{
aa = io.xint();
bb = io.xint();
cc = io.xint();
dd = io.xint();
check(aa, bb, cc, dd);
}
return 0;
}