题目链接

\(Description\)

  有一棵高度为\(h\)的满二叉树,点从\(1\)到\(2^h-1\)编号(无序)。每次你可以询问一个点的编号,交互库会返回其所有邻接点的编号。你需要在\(16\)次询问内确定这棵树根节点的编号。

  \(h\leq 7\)。

\(Solution\)

  考虑随便问一个点,然后任意找个相邻点走。这样如果不往回走,最差情况下是一直走到一个叶子,这样找走两遍,扩展出一条叶子到叶子的链,就可以往上扩展了。这样最多扩展\(1+2+\ldots+7=28\)个点,但是确定根节点就够了,即\(21\)个。

  还是不行。在深度比较浅时代价会比较高,但是深度浅了我们离根节点就更近。所以在离根足够近(距离为\(2\))直接BFS。这样代价为\(10+1+2+4=17\),但是最后一个点不需要查知道了,代价为\(16\)。

  思路很好理解,但是代码好难写啊。。弃疗了。参考个吧。orz\(yanQval\).

  要对初始点DFS两次,不管路径如何,我们记下两条路径经过点数\(c_1,c_2\),其深度就是\(\frac{c_1+c_2}{2}+1\)。如果有一次是向根节点延伸(\(c_1\neq c_2\)),就可以直接跳到经过路径上最靠近根的点。

  之后保证每次向上走,用之前的深度和新路径的点数同样可以跳。最后手动BFS。

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=150; int h,dgr[N],son[N][3],A1[N],A2[N];
bool vis[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
#define Check(x) if(dgr[x]==2) return x
inline void Query(int x)
{
vis[x]=1;
printf("? %d\n",x), fflush(stdout);
dgr[x]=read();
for(int i=0; i<dgr[x]; ++i) son[x][i]=read();
}
inline int Step(int x)
{
for(int i=0; i<dgr[x]; ++i) if(!vis[son[x][i]]) return son[x][i];
return son[x][0];
}
int Solve()
{
memset(vis,0,sizeof vis);
int h=read(), x=rand()%((1<<h)-1)+1, dep;
Query(x); Check(x);
if(dgr[x]==1) dep=1;
else
{
int cnt1=0, cnt2=0;
for(int v=Step(x); ; v=Step(v))
{
Query(v), A1[++cnt1]=v; Check(v);
if(dgr[v]==1) break;
}
for(int v=Step(x); ; v=Step(v))
{
Query(v), A2[++cnt2]=v; Check(v);
if(dgr[v]==1) break;
}
dep=(cnt1+cnt2>>1)+1;
if(cnt1>cnt2) x=A1[cnt1-dep+1];
else if(cnt1<cnt2) x=A2[cnt2-dep+1];
}
for(int cnt=0; dep<4/*not 5*/; cnt=0)
{
for(int v=Step(x); ; v=Step(v))
{
Query(v), A1[++cnt]=v; Check(v);
if(dgr[v]==1) break;
}
dep=dep+cnt+1>>1, x=A1[cnt-dep+1];
}
int a,b,c,d,e;
if(dep<h)
{
x=Step(x), Query(x); Check(x);
}
if(dep<h-1)
{
a=Step(x), Query(a); Check(a);
b=Step(x), Query(b); Check(b);
}
if(dep<h-2)
{
c=Step(a), Query(c); Check(c);
d=Step(a), Query(d); Check(d);
e=Step(b), Query(e); Check(e);
return Step(b);
}
return x;
} int main()
{
for(int T=read(); T--; printf("! %d\n",Solve()),fflush(stdout));
return 0;
}

Good Bye 2016 F.New Year and Finding Roots(交互)的更多相关文章

  1. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  2. 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016) F dfs序+树状数组

    Performance ReviewEmployee performance reviews are a necessary evil in any company. In a performance ...

  3. Good Bye 2016

    A - New Year and Hurry (water) #include <bits/stdc++.h> using namespace std; int main() { ]; ; ...

  4. CF IndiaHacks 2016 F Paper task 后缀数组

    题目链接:http://codeforces.com/problemset/problem/653/F 大意是给出一个只包含'('和')'的括号串,求有多少不同的子串是合法的括号串 解法:对于每一个后 ...

  5. 2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) F 区间dp

    Problem F Removal GameBobby Roberts is totally bored in his algorithms class, so he’s developed a li ...

  6. Good Bye 2015 F - New Year and Cleaning

    F - New Year and Cleaning 这题简直是丧心病狂折磨王.. 思路:容易想到这样一个转换,把整个矩形一起移动,矩形移出去的时候相当于一行或者一列. 为了优化找到下一个消去的点,我先 ...

  7. Good Bye 2014 F - New Year Shopping

    F - New Year Shopping 对于一种特殊的不可逆的dp的拆分方法.. 也可以用分治写哒. #include<bits/stdc++.h> #define LL long l ...

  8. April Fools Day Contest 2016 F. Ace It!

    F. Ace It! 题目连接: http://www.codeforces.com/contest/656/problem/F Description Input The only line of ...

  9. Good Bye 2016 A. New Year and Hurry【贪心/做题目每道题花费时间按步长为5等差增长,求剩余时间够做几道题】

    A. New Year and Hurry time limit per test 1 second memory limit per test 256 megabytes input standar ...

随机推荐

  1. Java基础-原码反码补码

    Java基础-原码反码补码 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 注意,我们这里举列的原码和反码只是为了求负数的补码,在计算机中没有原码,反码的存在,只有补码. 一.原码 ...

  2. 命令卸载ie11

    管理员运行cmd. 执行命令FORFILES /P %WINDIR%\servicing\Packages /M Microsoft-Windows-InternetExplorer-*11.*.mu ...

  3. Numpy - Pandas - Matplot 功能与函数名 速查

    用Python做数据分析,涉及到的函数实在是太多了,容易忘记,去网上查中文基本上差不到,英文有时候描述不清楚问题. 这里搞个针对个人习惯的函数汇总速查手册,下次需要用一个什么功能,就在这里面查到对应的 ...

  4. CF876 F 思维 枚举

    给你n个数,问有几个区间满足,区间内或操作大于区间内的任意数. 首先可以知道,两数或操作的结果必定不会小于两者间的最大值,也就是说对于一个区间中,不合法的状态只有两值或相等.那么我们可以考虑枚举每个数 ...

  5. FFprobe使用指南

    http://blog.csdn.net/stone_wzf/article/details/45378759 http://blog.chinaunix.net/uid-26000296-id-42 ...

  6. Java SSM框架之MyBatis3(五)MyBatis之ResultMap详解

    resultMap是Mybatis最强大的元素,它可以将查询到的复杂数据(比如查询到几个表中数据)映射到一个结果集当中. resultMap包含的元素: <!--column不做限制,可以为任意 ...

  7. 关于SQL注入,你应该知道的那些事

    戴上你的黑帽,现在我们来学习一些关于SQL注入真正有趣的东西.请记住,你们都好好地用这些将要看到的东西,好吗? SQL注入攻击因如下几点而是一种特别有趣的冒险: 1.因为能自动规范输入的框架出现,写出 ...

  8. Javascript摸拟自由落体与上抛运动 说明!

    JavaScript 代码 //**************************************** //名称:Javascript摸拟自由落体与上抛运动! //作者:Gloot //邮箱 ...

  9. linux(CentOS7)中安装erlang(20.3)以及rabbitmq(3.7.9)的步骤以及一些注意事项

    首先下载安装包,之后先安装erlang,安装erlang需要很多依赖,所以一步步来: 首先 wxWidgets会报错,这个不是必须的,可以不安装,不影响 然后需要安装一些必须的依赖: yum inst ...

  10. 修改history记录数门限

    你的 Bash 命令历史保存的历史命令的数量可以在 ~/.bashrc 文件里设置.在这个文件里,你可以找到下面两行: HISTSIZE=1000 HISTFILESIZE=2000 HISTSIZE ...