题目链接
CF1370F2 The Hidden Pair (Hard Version) (*2700)
题目描述
真的很难吗?
我们首先考虑找出第一个特殊点。
我们可以先求出这两个点路径中的任意一个点。发现询问 \(1 \sim n\) 就使我们需要的询问、
接下来以这个路径中的一个点为根来确定每个节点的深度。
接下来考虑二分出两个特殊点的路径中最深的点,容易发现这个东西是有单调性的。
我们找到一个点后,我们发现这个点就是路径的边界,那么我们就可以以找到的这个特殊点为根来根据我们的第一次询问确定另一个特殊点的深度。
这样就能找到两个特殊点了。
询问次数为 \(12\) 次,可以通过 F1。
我们继续考虑优化二分的边界。
假设这条路径为 \(dis\),根节点深度为 \(1\),那么最深的那个节点深度至少为 \(\lceil \frac{dis}{2} \rceil\),至多为 \(dis + 1\),
那么我们就将二分次数减少了 \(1\) 次。
此时总共询问 \(11\) 次,可以通过 F2。
参考代码
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll (i)=(a);i<=(b);(i)++)
#define forr(i,a,b) for(re ll (i)=(a);i>=(b);(i)--)
#define forll(i,a,b,c) for(re ll (i)=(a);i<=(b);(i)+=(c))
#define forrr(i,a,b,c) for(re ll (i)=(a);i>=(b);(i)-=(c))
#define forL(i,a,b,c) for(re ll (i)=(a);((i)<=(b)) && (c);(i)++)
#define forR(i,a,b,c) for(re ll (i)=(a);((i)>=(b)) && (c);(i)--)
#define forLL(i,a,b,c,d) for(re ll (i)=(a);((i)<=(b)) && (d);(i)+=(c))
#define forRR(i,a,b,c,d) for(re ll (i)=(a);((i)>=(b)) && (d);(i)-=(c))
#define pii pair<ll,ll>
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
//#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) (1ll*(x)/__gcd(x,y)*(y))
#define Sum(x,y) (1ll*((x)+(y))*((y)-(x)+1)/2)
#define x first
#define y second
template<typename T1,typename T2>bool Max(T1&x,T2 y){if(y>x)return x=y,1;return 0;}
template<typename T1,typename T2>bool Min(T1&x,T2 y){if(y<x)return x=y,1;return 0;}
ll _t_;
void _clear(){}
ll n;
ll x,y;
ll dep[1010];
vector<ll>G[1010];
vector<ll>D[1010];
vector<ll>q;
string s;
ll L,R;
pii ans;
pii ask(vector<ll>a)
{cout<<"? "<<a.size()<<' ';for(auto i:a)cout<<i<<' ';cout<<endl;ll x,y;cin>>x>>y;return {x,y};
}
void dfs(ll x,ll fa,ll deep)
{Max(R,deep);D[deep].pb(x);for(auto i:G[x])if(i!=fa)dfs(i,x,deep+1);
}
void solve()
{_clear();cin>>n;forl(i,1,n)G[i].clear();forl(i,2,n)cin>>x>>y,G[x].pb(y),G[y].pb(x);q.clear();forl(i,1,n)q.pb(i);pii num=ask(q);q.clear();forl(i,1,n)D[i].clear();R=0;dfs(num.x,0,1);L=max(1ll,(num.y+1)/2);Min(R,num.y+1);while(L<R){ll Mid=(L+R+1)/2;pii now=ask(D[Mid]);if(now.y==num.y)ans.x=now.x,L=Mid;elseR=Mid-1;}forl(i,1,n)D[i].clear();dfs(ans.x,0,1);pii num2=ask(D[num.y+1]);ans.y=num2.x;cout<<"! "<<ans.x<<' '<<ans.y<<endl;cin>>s;
}
int main()
{
// freopen("tst.txt","r",stdin);
// freopen("sans.txt","w",stdout);
// IOS;_t_=1;cin>>_t_;while(_t_--)solve();QwQ;
}