zoukankan      html  css  js  c++  java
  • CF1370F The Hidden Pair 题解

    Codeforces F1
    Codeforces F2
    Luogu F1
    Luogu F2

    Description.

    树上交互,有两个标记点。
    每次你询问一个点集,每次返回这个点集中到两标记距离和最小的点和这个距离和。
    F1 \(14\) F2 \(11\) 次内询问出两个标记点。

    Solution.

    首先,什么信息都没有的情况下肯定很困难。
    我们先询问全集,以返回的最小点为根,这样两个标记点就在两棵子树内,同时知道了链长。
    考虑 binary search,二分较大目标点的深度。
    每次可以把这层所有点拿出来问。
    判断 dis 是不是和链长相等来判断较深的那个点是不是在这个深度以下。
    这样需要 \(1+\log n+1 \approx 12\) 次,可以通过 F1。

    考虑较深那个点的值域,发现 \(\in[\frac {dis}2,dis]\),然后就节约了二分的一次。

    Coding.

    点击查看代码
    //Coded by leapfrog on 2021.10.29 {{{
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    const int N=1005;int as[N],at,dis;vector<int>d[N];
    struct edge{int to,nxt;}e[N<<1];int n,et,head[N],rx,fg[N];
    inline void adde(int x,int y) {e[++et]=(edge){y,head[x]},head[x]=et;}
    inline pair<int,int> ask()
    {
    	printf("? %d ",at);for(int i=1;i<=at;i++) printf("%d%c",as[i],i==at?'\n':' ');
    	fflush(stdout);int u,v;read(u,v);return make_pair(u,v);
    }
    inline void answer(int x,int y)
    {
    	printf("! %d %d\n",x,y),fflush(stdout);char ch[10];
    	scanf("%s",ch);if(*ch=='I') exit(0);
    }
    inline void dfs0(int x,int fa,int dep,int rt)
    {
    	d[dep].push_back(x),fg[x]=rt;
    	for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) dfs0(e[i].to,x,dep+1,rt);
    }
    inline char check(int w)
    {
    	if(d[w].empty()) return 0;else at=d[w].size();
    	for(int i=1;i<=at;i++) as[i]=d[w][i-1];
    	pair<int,int>q=ask();if(q.second==dis) return rx=q.first,1;else return 0;
    }
    inline void solve()
    {
    	read(n),et=0;for(int i=1;i<=n;i++) head[i]=fg[i]=0;
    	for(int i=1,x,y;i<n;i++) read(x,y),adde(x,y),adde(y,x);
    	at=n;for(int i=1;i<=n;i++) as[i]=i,d[i].clear();
    	pair<int,int>q=ask();int rt=q.first;dis=q.second;
    	int l=(dis+1)/2,r=dis+1,rs=r;d[1].push_back(rt);
    	for(int i=head[rt];i;i=e[i].nxt) dfs0(e[i].to,rt,2,e[i].to);
    	while(l<=r) {int md=(l+r)>>1;if(check(md)) rs=md,l=md+1;else r=md-1;}
    	int ds=dis-rs+2;at=0;
    	for(size_t i=0;i<d[ds].size();i++) if(fg[d[ds][i]]^fg[rx]) as[++at]=d[ds][i];
    	q=ask(),answer(rx,q.first);
    }
    int main() {int Ca;for(read(Ca);Ca--;) solve();return 0;}
    
  • 相关阅读:
    笔记20200430:异常机制
    笔记20200429:面向对象
    笔记20200429:数组
    笔记20200428:方法的定义及调用、重装、命令行参数、可变参数、递归
    笔记20200427:javadoc文档、Scanner、顺序结构、选择结构、循环结构
    CSS+DIV入门第一天基础视频 CSS选择器层叠性和继承性
    网站实战 从效果图开始CSS+DIV 布局华为网站
    CSS中的间距设置与盒子模型
    CSS选择器
    CSS颜色及文本字体
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15481890.html
Copyright © 2011-2022 走看看