给定一个长度为 的 串,定义 为 到 区间内 子序列的数量,通过最多 次交互,确定这个 串的构成。
可以从莫队的思想,也就是增量,来思考如何解决。
如果说我们已经知道了 ,接下来我们询问 的值,相当于往 的串的后面接了一个字符上去。
- 如果这一次询问的答案不同于 ,说明有新的 子序列产生,那么一定是引入了一个 导致的。
- 如果这一次询问的答案和 相同,那么有两种情况。
- 位引入的是一个
- 位引入的是一个 ,但是 内一个 也没有。
为了方便,我们直接利用上述原理从左到右构建这个串,也就是从小到大地询问 的答案。
那么首先需处理第一个答案非零的位置,这说明当前这一位一定是 ,并且前面是 的结构(因为前面的询问得到的答案都是 ),具体来说,前面 的个数就是当前这一次询问的答案(注意前面不一定有 ,但一定有 )。
接着我们就可以继续安心地询问了,由于我们确保了已经有若干个 出现在串中,那么如果当前得到的答案和上一次相同,当前位就一定是 ;否则就是 。
唯一一种无解的情况,就是我们始终没有询问到一个非零的答案,这样的话这个串可能是 ,或者 ,亦或是 ,所以是无法确定的。
| #include<bits/stdc++.h> |
| #define int long long |
| using namespace std; |
| int n; |
| inline int q(int l,int r){cout<<"? "<<l<<' '<<r<<endl;int ans;cin>>ans;return ans;} |
| char s[100010]; |
| inline void solve() |
| { |
| cin>>n; |
| int p=2,las_ans; |
| while(p<=n) |
| { |
| int ans=q(1,p); |
| if(ans!=0) |
| { |
| s[p]='1'; |
| for(int i=1;i<=p-1-ans;++i)s[i]='1'; |
| for(int i=p-ans;i<=p-1;++i)s[i]='0'; |
| las_ans=ans; |
| p++; |
| goto NEXTSTEP; |
| } |
| p++; |
| } |
| cout<<"! IMPOSSIBLE"<<endl;return ; |
| NEXTSTEP:; |
| while(p<=n) |
| { |
| int ans=q(1,p); |
| if(ans==las_ans) |
| { |
| s[p]='0'; |
| } |
| else |
| { |
| s[p]='1'; |
| las_ans=ans; |
| } |
| p++; |
| } |
| cout<<"! "; |
| for(int i=1;i<=n;++i)cout<<s[i]; |
| cout<<endl; |
| } |
| signed main() |
| { |
| int T; |
| cin>>T; |
| while(T--) |
| solve(); |
| return 0; |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效