博客园 首页 私信博主 显示目录 隐藏目录 管理

题解 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;
}
posted @ 2020-11-22 13:59  Flash_plus  阅读(133)  评论(0编辑  收藏  举报