题解 CF1451B 【Non-Substring Subsequence】
题目大意
给你一个长度为 \(n\) \(0/1\) 字符串,以及 \(m\) 个询问。
每个询问会告诉你一个 \(l, r\)。
问你在原字符串中有没有一个子序列和子串 \(s_l \to s_r\) 一样。
题解
你考虑只改变首或者尾,看能不能找到符合要求的子序列。
我们来验证,如果首 & 尾都无法找到一样的替代。
那么你也不能找到和首/尾 \(2\) 位一样的去替代,因为第一位都没有一样的了。
反之,如果你可以找到一个字符去代替首/尾,那么他已经是一个和原串相同的子序列了。
至于怎么找,就只要记录下前面第一次出现 \(0/1\) 的位置,记录下后面第一次出现 \(0/1\) 的位置。
然后判断下就行了。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define Rep(x, a, b) for(int x = a; x <= b; ++ x)
#define Dep(x, a, b) for(int x = a; x >= b; -- x)
#define Next(i, x) for(int i = head[x]; i; i = edge[i].nxt)
int read() {
char c = getchar(); int f = 1, x = 0;
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
char s[101];
signed main() {
int T = read();
while(T --) {
int n = read(), q = read(), pla = 0, pla2 = 0, Pla = 0, Pla2 = 0;
Rep(i, 1, n) {
scanf("%c", &s[i]);
if(s[i] == '0' && pla == 0) pla = i;
else if(s[i] == '1' && pla2 == 0) pla2 = i;
}
Dep(i, n, 1) {
if(s[i] == '0' && Pla == 0) Pla = i;
else if(s[i] == '1' && Pla2 == 0) Pla2 = i;
}
Rep(i, 1, q) {
int flag = 0, l = read(), r = read();
if(s[l] == '0' && pla < l) flag = 1;
if(s[r] == '0' && Pla > r) flag = 1;
if(s[r] == '1' && Pla2 > r) flag = 1;
if(s[l] == '1' && pla2 < l) flag = 1;
if(flag) puts("YES"); else puts("NO");
}
}
return 0;
}