训练内容:
1场cf,1场eoj月赛,2场牛客多校,9个cf上难度1600-2000的题
推荐题目:
F2. The Hidden Pair (Hard Version)
交互题,https://codeforces.com/contest/1370/problem/F2一开始就有思路。
首先找所有的点,输出一定是 这条路径中的一个点 和 这条路径的长度
然后我们以已知的这个点为根dfs,记录每层有什么点。
假设路径长度为k,答案之一距离根的max肯定大于等于(k+1)/2,我们就先找这个远的点。
下界为(k+1)/2,上界为k,二分查找即可。
得到这个点之后,再以这个点为根,那么距离这个点k距离的点集中再查询一次,即可得到另一个点
int n,m;
char str[N];
int f[M];
vector<int> v[M],lvl[M],tmp;
pt query(vector<int> &tt)
{
if(!tt.size()) return mp(-1,-1);
cout<<"? "<<tt.size();
for(int x:tt) cout<<" "<<x;
cout<<endl;
int a,b;
cin>>a>>b;
return mp(a,b);
}
void dfs(int x,int fa,int dep)
{
m=max(m,dep);
lvl[dep].pb(x);
for(int y:v[x]){
if(y!=fa){
dfs(y,x,dep+1);
}
}
}
int main()
{
int t;r(t);
while(t--){
r(n);
m=0;
tmp.clear();
lvl[0].clear();
FOR(i,1,n){
v[i].clear();
lvl[i].clear();
tmp.pb(i);
}
FOR(i,1,n-1){
int a,b;rr(a,b);
v[a].pb(b);
v[b].pb(a);
}
pt res=query(tmp);
int root=res.fi,dep=res.se;
dfs(root,0,0);
int l=(dep+1)/2,r=min(m,dep),ans1;
while(l<=r){
int mid=l+r>>1;
res=query(lvl[mid]);
if(res.se==dep){
ans1=res.fi;
l=mid+1;
}
else r=mid-1;
}
FOR(i,0,n) lvl[i].clear();
dfs(ans1,0,0);
res=query(lvl[dep]);
cout<<"! "<<ans1<<' '<<res.fi<<endl;
string s;
cin>>s;
}
return 0;
}