日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces - 1370F2 The Hidden Pair (Hard Version)(交互题+二分)

發布時間:2024/4/11 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 1370F2 The Hidden Pair (Hard Version)(交互题+二分) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一棵無向無根樹,事先確定好了兩個點 s 和 t ,現在需要通過詢問找到這兩個點

每次詢問可以給出一個點集,系統會返回點集中距離點 s 和點 t 距離之和最小的那個點以及其距離,如果有多個符合條件的點,會返回任意一個,比如詢問了點集 A = { s1 , s2 , ... , sk } ,則系統會返回一個點 v ∈ A 并且 dist( s , v ) + dist( t , v ) 最小

簡單版本的是可以詢問 14 次,困難版本的是只能詢問 11?次

題目分析:14 和 11 次對應著數據范圍 1000 ,應該是 logn 的算法,所以我們應該盡量往上面靠攏

首先因為無從下手,所以可以先問一遍全部的點,獲得到一個點 rt ,且距離之和為 len,畫畫圖應該不難看出,點 rt 滿足的一個性質是,一定位于點 s 到點 v 的這條路徑上

下面的轉換可能比較難想,但是如果想到了的話剩下的就比較簡單了

我們可以以點 rt 點為根,遍歷一遍整棵樹后跑出每個點的深度,此時對于每個點的深度以及 dist( s , v ) + dist( t , v ),可以看出這兩個值之間滿足著單調性,這樣我們就可以在深度上二分找到:距離之和等于 len 的最大深度的那個點,這個點就是 s 或者 t 中的一個點,再用找到的這個點建樹,詢問深度為 len 的那一層的所有點,得到的答案就是另外一個點了

如果初始時設置 l = 1 , r = n ,那么 F1 就這樣解決了,主要是該如何解決 F2?

很顯然,詢問全部的 n 個點,和知道其中一個點后再通過一次操作得到另外一個點,這兩次操作是無可避免的,優化點只能出自于二分上面 ,對于二分,我們可以做的優化就是縮小初始的范圍了

因為初始時找到的 rt 一定是位于 s 到 t 的路徑上的,又因為我們是要借助二分尋找距離之和等于 len 的最大深度,那么當這個 rt 在 s 到 t 這條路徑的最中間時,左端點最小,取到了??的位置,相應的,我們如果假設 rt 這個點初始時就是 s 點或者 t 點的話,那么右端點最多也就是 len 了,所以右端點我們設置為 min( len , max_deep ) 就好了,max_deep 是建樹后的最大深度

代碼:
?

#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e3+100;int n,max_deep;vector<int>node[N],deep[N];pair<int,int> query(int dep) {printf("? %d",deep[dep].size());for(auto v:deep[dep])printf(" %d",v);puts("");fflush(stdout);int rt,len;scanf("%d%d",&rt,&len);return make_pair(rt,len); }void dfs(int u,int fa,int dep) {max_deep=max(max_deep,dep);deep[dep].push_back(u);for(auto v:node[u]){if(v==fa)continue;dfs(v,u,dep+1);} }void build(int rt) {max_deep=0;for(int i=0;i<=n;i++)deep[i].clear();dfs(rt,-1,0); }pair<int,int> get_root() {printf("? %d",n);for(int i=1;i<=n;i++)printf(" %d",i);puts("");fflush(stdout);int rt,len;scanf("%d%d",&rt,&len);return make_pair(rt,len); }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--){scanf("%d",&n);for(int i=1;i<=n;i++)node[i].clear();for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}pair<int,int>temp=get_root();int rt=temp.first,len=temp.second;build(rt);int l=(len+1)/2,r=min(max_deep,len),s;while(l<=r){int mid=l+r>>1;temp=query(mid);int p=temp.first,d=temp.second;if(d==len){s=p;l=mid+1;}elser=mid-1;}build(s);int t=query(len).first;printf("! %d %d\n",s,t);fflush(stdout);scanf("%*s");}return 0; }

?

總結

以上是生活随笔為你收集整理的CodeForces - 1370F2 The Hidden Pair (Hard Version)(交互题+二分)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。