「雜題亂刷2」CF1370F2

wangmarui發表於2024-11-10

題目連結

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;
        else
            R=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;
}