CF2032D 题解
CF2032D 题解
题意
有一张特殊结构的树图。
通过交互来确定每个节点的父节点,即这棵树的结构。
具体还是直接上CF看吧,在题解里面太详尽地描述有点浪费时间了。
分析
可以发现
可以从
但是发现这种写法好像实在无法满足
于是瞟了一眼题解。。。
但是只看了 Hint ,就突然醒悟了。
可以发现第一层节点的编号一定是连续且递增的,这个结论同样也可以通过反证法证明。
那么我们可以用很少的代价先确定第一层所有的节点。
之后直接从小到大询问,发现如果询问失败,那么这个节点实际上可以直接丢掉了。。。
Solution 1
那么就可以用一个 set 来维护询问的过程,没用的节点就直接删掉就可以了。
还有一个优化,就是当 set 里面只有一个节点的时候,这个唯一的节点一定是当前所需要确定的节点的父亲。
否则它的父亲只能是
这是我差不多自己想出来的玄学做法。
Solution 2
其实还会发现一个性质,就是当前需要确定的节点一旦确定下来,那么它也一定是被插到了 set 的最尾部,所以大可不必用 set 来维护,
在序列上跑一个双指针就可以了。
即:
这个是std的做法,好聪明。
Code
1
2
#include<bits/stdc++.h> using namespace std; int T,n; int main() { cin>>T; auto query=[&](int x,int y) { int ans; cout<<"? "<<x<<' '<<y<<endl; cin>>ans; return ans; }; while(T--) { cin>>n; vector<int> fa(n+1,0); int l=1,r=2; while(query(l,r)) r++; fa[r]=l,l++,r++; while(r<=n-1) { while(query(l,r))l++; fa[r]=l,l++,r++; } cout<<"!"; for(int i=1;i<n;++i)cout<<' '<<fa[i]; cout<<endl; } return 0; }
Tip
有一个值得注意的小地方是,交互题直接用endl可以在换行的同时起到刷新缓冲区的效果。
本文来自博客园,作者:Hanggoash,转载请注明原文链接:https://www.cnblogs.com/Hanggoash/p/18528628
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效