1 条题解
-
0
自动搬运
来自洛谷,原作者为

离散小波变换°
有志不在年高,无志空长百岁搬运于
2025-08-24 22:59:56,当前版本为作者最后更新于2024-07-15 14:36:53,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
很有意思的题。
题解
先从简单的情形开始考虑。因为原序列一定是一个合法的括号序列,于是第一个字符一定是 。要想确定第二个字符,只需要利用一次询问 ,如果结果是 那么第二个字符是 ,否则是 。
- 对于 的情况,说明它与第一个字符组成了一个匹配,我们解决掉了一个子问题,接下来从第三个字符开始解决问题就行;
- 对于 的情况,说明第一个字符对应的括号下面有一些子括号问题,对于子问题,容易想到可以递归地去解决。
具体而言,我们维护两个变量 和 , 表示当前正在处理第 个字符, 表示目前父括号对左括号的下标。
$${\verb!(...)(...)!\operatorname*{\verb!(!}_p\verb!(...)(...)!\operatorname*{\verb!?!}_{i}\verb!???!} $$如果查询 结果为 ,说明 位置是一个右括号,回溯;否则说明 位置是一个左括号,递归地求解 。递归处理完毕后将 设置为当前第一个尚未确定的字符的下标。
由于每次询问之后 都会增加 ,于是总询问次数不超过 。数据范围 属于是给多了。
参考代码
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 3; bool check(int l, int r){ cout << "? " << l << " " << r << endl; string result; cin >> result; return result == "Yes"; } char C[MAXN]; void dfs(int &i, int p){ while(1){ if(check(p, i)){ C[i] = ')', i ++; return; } else { C[i] = '(', i ++; dfs(i, i - 1); } } } int main(){ int n; cin >> n; int i = 1; while(i <= n){ C[i] = '(', i ++; dfs(i, i - 1); } cout << "! " << C + 1 << endl; return 0; }
- 1
信息
- ID
- 10450
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者