题解:CF1370F2 The Hidden Pair (Hard Version)

2024-05-26 03:36

本文主要是介绍题解:CF1370F2 The Hidden Pair (Hard Version),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意

交互题。 给你一棵 n n n 个点的树,需要得出树上两个点 X , Y X,Y X,Y 的位置。你可以向评测机询问一个点集,评测机会回答点集中与 X , Y X,Y X,Y 距离和最小的点,以及这个距离和。询问不超过 11 11 11 次。

思路

询问次数不能超过 11 11 11 次,这个数字与 log ⁡ n \log n logn 的值很接近。考虑先对所有 n n n 个点进行询问,这样就可以得到 X , Y X,Y X,Y 之间的距离,和一个必定在 X , Y X,Y X,Y 路径上的点。设这个点为 r t rt rt X , Y X,Y X,Y 之间的距离为 d i s dis dis。如果我们以 r t rt rt 为树根,那么对于树中深度为 d e p dep dep 的点集 { A } \{A\} {A},且 d e p dep dep 大于等于 X , Y X,Y X,Y 中较小的深度,我们对其进行询问:

  • 如果询问得到的距离和为 d i s dis dis,则表示询问得到的点在 X , Y X,Y X,Y 的路径上,即 X , Y X,Y X,Y 中较大的深度大于等于 d e p dep dep
  • 如果询问得到的距离和大于 d i s dis dis,则表示该深度的点中没有在 X , Y X,Y X,Y 的路径上的,即 X , Y X,Y X,Y 中较大深度小于 d e p dep dep

对于第一种情况询问到的点都可能是 X , Y X,Y X,Y 中深度较大的点,不妨令 d e p X ≥ d e p Y dep_X\ge dep_Y depXdepY。考虑二分,区间为 [ ⌊ d i s 2 ⌋ , min ⁡ ( d i s , D e p ) ] [\lfloor\cfrac{dis}{2}\rfloor,\min(dis,Dep)] [⌊2dis,min(dis,Dep)],其中 D e p Dep Dep 为最大深度。每一轮都询问一次深度为 m i d mid mid 的点集,按照上述两种情况二分,最终可以得到深度较大的 X X X。然后我们以 X X X 为树根,然后询问深度为 d i s dis dis 的点集,得到的点即为 Y Y Y

为什么二分区间上界可以这么取?

感性理解一下,因为我们要处理出 X , Y X,Y X,Y 较深的一个点,所以深度小于 d i s ( X , Y ) dis(X,Y) dis(X,Y) 的点都不会是那个较深的点。

实现

实现没什么难点,注意每次询问/回答都要 fflush(stdout)

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005;
vector<int> mp[maxn << 1];
void addEdge(int u,int v) {mp[u].push_back(v);
}
vector<int> a[maxn]; int Dep;
void dfs(int u,int fa,int dep) {a[dep].push_back(u);Dep = max(Dep,dep);for (auto v : mp[u]) {if (v == fa) continue;dfs(v,u,dep + 1);}
}
pair<int,int> Query(const vector<int> &ask) {printf("? %d",ask.size());for (auto x : ask) printf(" %d",x);puts(""); fflush(stdout);int x,d;scanf("%d %d",&x,&d);return make_pair(x,d);
}
pair<int,int> Solve(int n,const vector<pair<int,int> > &edge) {for (int i = 1;i <= n;i ++)mp[i].clear();for (int i = 0;i <= Dep;i ++) a[i].clear();Dep = 0;for (auto E : edge) {int u = E.first, v = E.second;addEdge(u,v); addEdge(v,u);}vector<int> ask;for (int i = 1;i <= n;i ++) ask.push_back(i);pair<int,int> res = Query(ask);int rt = res.first, sum = res.second;dfs(rt,0,0);int l = sum >> 1, r = min(Dep,sum);int X = 0;while (l <= r) {int mid = l + r >> 1;res = Query(a[mid]);if (res.second == sum) l = mid + 1, X = res.first;else r = mid - 1;}for (int i = 0;i <= Dep;i ++) a[i].clear();Dep = 0; dfs(X,0,0);return make_pair(X, Query(a[sum]).first);
}
int T,n; char AC_or_WA[maxn];
vector<pair<int,int> > Edge;
int main() {scanf("%d",&T);while (T --) {scanf("%d",&n);Edge.clear();for (int i = 1,u,v;i < n;i ++) {scanf("%d%d",&u,&v);Edge.emplace_back(u,v);}pair<int,int> ans = Solve(n,Edge);printf("! %d %d\n",ans.first,ans.second);fflush(stdout);scanf("%s",AC_or_WA + 1);}return 0;
}

这篇关于题解:CF1370F2 The Hidden Pair (Hard Version)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1003423

相关文章

提示:Decompiled.class file,bytecode version如何解决

《提示:Decompiled.classfile,bytecodeversion如何解决》在处理Decompiled.classfile和bytecodeversion问题时,通过修改Maven配... 目录问题原因总结问题1、提示:Decompiled .class file,China编程 bytecode

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

Maven创建项目中的groupId, artifactId, 和 version的意思

文章目录 groupIdartifactIdversionname groupId 定义:groupId 是 Maven 项目坐标的第一个部分,它通常表示项目的组织或公司的域名反转写法。例如,如果你为公司 example.com 开发软件,groupId 可能是 com.example。作用:groupId 被用来组织和分组相关的 Maven artifacts,这样可以避免

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

【秋招笔试】9.07米哈游秋招改编题-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收集 100+ 套笔试题,笔试真题 会在第一时间跟新 🍄 题面描述等均已改编,如果和你笔试题看到的题面描述

LeetCode 第414场周赛个人题解

目录 Q1. 将日期转换为二进制表示 原题链接 思路分析 AC代码 Q2. 范围内整数的最大得分 原题链接 思路分析 AC代码 Q3. 到达数组末尾的最大得分 原题链接 思路分析 AC代码 Q4. 吃掉所有兵需要的最多移动次数 原题链接 思路分析 AC代码 Q1. 将日期转换为二进制表示 原题链接 Q1. 将日期转换为二进制表示 思路分析

Jenkins 通过 Version Number Plugin 自动生成和管理构建的版本号

步骤 1:安装 Version Number Plugin 登录 Jenkins 的管理界面。进入 “Manage Jenkins” -> “Manage Plugins”。在 “Available” 选项卡中搜索 “Version Number Plugin”。选中并安装插件,完成后可能需要重启 Jenkins。 步骤 2:配置版本号生成 打开项目配置页面。在下方找到 “Build Env

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

Learn ComputeShader 09 Night version lenses

这次将要制作一个类似夜视仪的效果 第一步就是要降低图像的分辨率, 这只需要将id.xy除上一个数字然后再乘上这个数字 可以根据下图理解,很明显通过这个操作在多个像素显示了相同的颜色,并且很多像素颜色被丢失了,自然就会有降低分辨率的效果 效果: 但是这样图像太锐利了,我们加入噪声去解决这个问题 [numthreads(8, 8, 1)]void CSMain(uint3 id