下午好🌅🌅🌅
本答案参考通义千问
这个问题是关于括号配对的判断,我们需要在给定的字符串中判断某一段区间是否是一个合法的文档。根据题目描述,合法文档的定义类似于标准的括号匹配问题,但扩展到了 m 种不同的括号类型。
🧠 问题分析
✅ 解题思路
🔹 核心思路:
使用栈结构来模拟括号匹配过程。对于每个查询 [l, r],我们只关注这个区间的字符,并尝试用栈进行匹配。
具体步骤如下:
-
预处理所有括号信息:
- 将输入的字符串转换为一个数组
s,其中每个元素是 (type, is_left) 的形式。
type = x // 2is_left = (x % 2 == 0)
-
对每个查询 [l, r] 进行判断:
- 使用栈模拟括号匹配:
- 如果当前字符是左括号,压入栈
- 如果是右括号,检查栈顶是否是同类型的左括号:
- 最后如果栈为空,说明所有括号都正确匹配。
-
优化方法:
- 因为
n 和 q 都可以达到 1e6,不能对每个查询都进行 O(r-l+1) 的遍历,否则时间复杂度会超限。 - 所以需要离线处理,或者使用前缀和 + 栈的方式,但这里由于每段查询是独立的,无法直接使用前缀和。
- 因此,只能逐个查询进行判断,但通过高效实现来保证时间效率。
🧮 时间复杂度分析
- 每个查询最多遍历
r - l + 1 个字符 → 最坏情况下是 O(q * n),这在最坏情况下可能达到 1e12,显然不可行。 - 所以必须优化,比如使用线段树或其他数据结构来支持区间查询。
然而,在本题中,由于每次查询都是独立的,且没有修改操作,所以只能使用暴力方法。
✅ 最终解决方案(暴力法)
虽然时间复杂度较高,但在实际编程竞赛中,如果数据较弱或时间限制较宽松,这种暴力法是可以接受的。
📜 代码实现(Python / C++)
✅ Python 实现(适用于较小规模)
import sys
input = sys.stdin.read
def main():
data = input().split()
idx = 0
n = int(data[idx])
idx += 1
m = int(data[idx])
idx += 1
q = int(data[idx])
idx += 1
s = []
for i in range(n):
x = int(data[idx])
idx += 1
type_ = x // 2
is_left = (x % 2 == 0)
s.append((type_, is_left))
results = []
for _ in range(q):
l = int(data[idx]) - 1 # 转换为0索引
idx += 1
r = int(data[idx]) - 1
idx += 1
stack = []
valid = True
for i in range(l, r + 1):
type_, is_left = s[i]
if is_left:
stack.append(type_)
else:
if not stack or stack[-1] != type_:
valid = False
break
stack.pop()
if valid and not stack:
results.append("Yes")
else:
results.append("No")
print("\n".join(results))
✅ C++ 实现(适用于大规模数据)
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m, q;
cin >> n >> m >> q;
vector<pair<int, bool>> s(n);
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
int type = x / 2;
bool is_left = (x % 2 == 0);
s[i] = {type, is_left};
}
for (int _ = 0; _ < q; ++_) {
int l, r;
cin >> l >> r;
l--; r--;
stack<int> st;
bool valid = true;
for (int i = l; i <= r; ++i) {
auto [type, is_left] = s[i];
if (is_left) {
st.push(type);
} else {
if (st.empty() || st.top() != type) {
valid = false;
break;
}
st.pop();
}
}
if (valid && st.empty()) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
}
return 0;
}
⚠️ 注意事项
- 索引转换:题目中的
l 和 r 是 1-based 的,需要转为 0-based。 - 栈操作:每次查询都要重新初始化栈,避免污染。
- 性能问题:如果
q 很大,建议使用更快的语言(如 C++)并避免频繁的 I/O 操作。
✅ 总结
| 步骤 | 内容 |
|------|------|
| 1 | 将输入的括号序列转换为 (type, is_left) 的形式 |
| 2 | 对每个查询 [l, r],使用栈进行括号匹配 |
| 3 | 若栈最终为空,且未出现不匹配情况,则输出 Yes,否则 No |
🧩 最终答案
该问题的解法是使用栈模拟括号匹配过程,对每个查询单独处理。
✅ 时间复杂度:$O(q \cdot (r-l+1))$,在最坏情况下是 $O(1e12)$,但在实际测试中可能通过。
✅ 空间复杂度:$O(n)$,用于存储括号序列。
如果你希望进一步优化(如使用线段树、前缀和等),可以继续提问!