题目链接


\(Description\)

有一棵\(n\)个点的树。你需要在\(11111\)次询问内确定出这棵树的形态。每次询问你给定两个非空且不相交的点集\(S,T\)和一个点\(u\),交互库会告诉你满足\(x\in S,y\in T\),且\(x\to y\)经过了\(u\)的点对\((x,y)\)的数量。

\(n\leq500\)。

\(Solution\)

不妨假设以\(1\)为根。首先如果想知道\(y\)是否在\(x\)的子树内,询问\(S=\{1\},T=\{y\},u=x\)就可以了(同样可以扩展到某点集中有多少个点在\(x\)子树内)。

那么对于每个点\(i\),询问\(S=\{1\},T=\{2,3,...,n\},u=i\),就可以知道\(i\)子树的大小\(size_i\)。

有什么用呢。。把所有点按\(size_i\)从大到小排序,那么该序列中每个点的父节点一定在它的左边。

(PS:这个序列还可以增量构造出来:考虑在已有\(1...i\)的序列中加入\(i+1\),二分找到一个最靠右的点\(p\),满足\(a_1,a_2,...,a_p\)没有点在\(i+1\)的子树中,然后把\(i+1\)插入到\(a_p\)后面即可。需要\(O(n\log n)\)次询问。)

考虑从右往左扫这个序列,对每个节点找出它直属的儿子。

假设当前是点\(i\),设\(i\)后面还没有找到父亲的点集是\(P\)。首先查一次\(P\)中是否没有点在\(i\)的子树中。\(S=\{1\},T=P,u=i\)询问一次即可。

若\(P\)中存在\(i\)子树内的点,可以二分找出\(P\)中最靠左的一个\(i\)的儿子\(P_j\),连边\((i,p)\)。然后再对\(P'=\{P_{j+1},P_{j+2},...\}\)继续重复上边过程即可。

询问次数\(O(n\log n)+2n\)。(数据实测最多\(<5500\))(有\(200\)组数据=-=)


#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
#define pc putchar
#define Flush() fflush(stdout)
#define gc() getchar()
typedef long long LL;
const int N=505; int id[N],sz[N],fa[N]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
inline bool cmp(int a,int b)
{
return sz[a]>sz[b];
}
int Query_Size(int x,int n)
{
printf("1\n1\n%d\n",n-1);
for(int i=2; i<=n; ++i) printf("%d ",i);
return printf("\n%d\n",x),Flush(),read();
}
int Query_Exist(int x,const std::vector<int> &vec,int r)//vec中存在x子树中的点
{
printf("1\n1\n%d\n",r);
for(int i=0; i<r; ++i) printf("%d ",vec[i]);
return printf("\n%d\n",x),Flush(),read();
} int main()
{
const int n=read();
for(int i=1; i<=n; ++i) id[i]=i;
sz[1]=n;
for(int i=2; i<=n; ++i) sz[i]=Query_Size(i,n);
std::sort(id+1,id+1+n,cmp);
std::vector<int> vec;
for(int i=n; i; --i)
{
int x=id[i];
std::vector<int> P=vec,tmp;
while(!P.empty()&&Query_Exist(x,P,P.size()))
{
int l=1,r=P.size(),mid;
while(l<r)
if(Query_Exist(x,P,mid=l+r>>1)) r=mid;
else l=mid+1;
fa[P[--l]]=x;
auto it=P.begin();
while(l--) tmp.push_back(*it++);
P.erase(P.begin(),++it);
}
for(auto v:P) tmp.push_back(v);
vec=tmp, vec.push_back(x);
}
puts("ANSWER");
for(int i=2; i<=n; ++i) printf("%d %d\n",fa[i],i); return 0;
}

Codeforces.1129E.Legendary Tree(交互 二分)的更多相关文章

  1. Codeforces 1129E - Legendary Tree(思维题)

    Codeforces 题面传送门 & 洛谷题面传送门 考虑以 \(1\) 为根,记 \(siz_i\) 为 \(i\) 子树的大小,那么可以通过询问 \(S=\{2,3,\cdots,n\}, ...

  2. Codeforces.714D.Searching Rectangles(交互 二分)

    题目链接 \(Description\) 在一个\(n*n\)的二维平面中有两个不相交的整点矩形,每次可以询问两个矩形有几个完全在你给出的一个矩形中.200次询问内确定两个矩形坐标. \(Soluti ...

  3. Codeforces 1129 E.Legendary Tree

    Codeforces 1129 E.Legendary Tree 解题思路: 这题好厉害,我来复读一下官方题解,顺便补充几句. 首先,可以通过询问 \(n-1​\) 次 \((S=\{1\},T=\{ ...

  4. Problem - D - Codeforces Fix a Tree

    Problem - D - Codeforces  Fix a Tree 看完第一名的代码,顿然醒悟... 我可以把所有单独的点全部当成线,那么只有线和环. 如果全是线的话,直接线的条数-1,便是操作 ...

  5. Codeforces Round #381 (Div. 2) D. Alyona and a tree 树上二分+前缀和思想

    题目链接: http://codeforces.com/contest/740/problem/D D. Alyona and a tree time limit per test2 secondsm ...

  6. Codeforces E. Alyona and a tree(二分树上差分)

    题目描述: Alyona and a tree time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  7. Codeforces Round #381 (Div. 2)D. Alyona and a tree(树+二分+dfs)

    D. Alyona and a tree Problem Description: Alyona has a tree with n vertices. The root of the tree is ...

  8. Codeforces.862D.Mahmoud and Ehab and the binary string(交互 二分)

    题目链接 \(Description\) 有一个长为\(n\)的二进制串,保证\(01\)都存在.你可以询问不超过\(15\)次,每次询问你给出一个长为\(n\)的二进制串,交互库会返回你的串和目标串 ...

  9. Codeforces.810D.Glad to see you!(交互 二分)

    题目链接 \(Description\) 有一个大小为\(k\)的集合\(S\),元素两两不同且在\([1,n]\)内.你可以询问不超过\(60\)次,每次询问你给出\(x,y\),交互库会返回\(\ ...

随机推荐

  1. C#匿名对象(转JSON)

    多类型匿名对象 var result = new { pages = , users = new System.Collections.ArrayList { ,name="}, ,name ...

  2. LOJ #6485 LJJ 学二项式定理

    QwQ LOJ #6485 题意 求题面中那个算式 题解 墙上暴利 设$ f(x)=(sx+1)^n$ 假设求出了生成函数$ f$的各项系数显然可以算出答案 因为模$ 4$的缘故只要对于每个余数算出次 ...

  3. 迭代和JDB

    迭代和JDB 使用C(n,m)=C(n-1,m-1)+C(n-1,m)公式进行递归编程实现求组合数C(m,n)的功能. 源代码 public class Combination { public st ...

  4. jquery.form插件 提交表单 type="hidden"取不到值的问题记录

    1.外国文献:说可以改成其他的(非hidden),再加style="display:none"隐藏. <INPUT type="password" sty ...

  5. IE兼容事件绑定V1.0

    想要兼容IE678,少用原型,因为它们没有完全实现ECMA-262规范 (function(window){ //兼容IE678时少用原型,因为它没有完全遵循ECMA-262规范 //衬垫代码:isA ...

  6. C++入门篇十二

    成员变量和成员属性: 静态成员函数和静态成员变量是不属于对象的,所以不占有空间,非静态成员是属于对象的,占有存储空间,空类大小1 #include "pch.h" #include ...

  7. USACO15DEC最大流MaxFlow

    传送门 这是个假的最大流,其实是一个用树剖+线段树就能解决的事情 题目中的道路会对路径上的造成压力,最后询问最大的压力 其实就等价于对每条路径上的点加上 1 的权值,并且最后询问整个树中的最大值 然后 ...

  8. redis哨兵主从自动切换

    1.用的是TP5框架,改写框架自带的redis类 thinkphp/library/think/cache/driver/Redis.php //两台服务器都配置好了监控哨兵 //主从配置要设置好密码 ...

  9. 关于在eclipse中添加windowbuilder插件的问题

    最近在学习GUI,发现我的Eclipse中没有windowbuilder插件,之后按照百度搜索,按照网上教程,去安装时,发现下载网页已经更新,造成了很多问题, 不过问题不大,我已经找到了解决方法: 安 ...

  10. 使用Node.js+Hexo+Github搭建个人博客

    一.为什么要花时间去搭建个人博客? 首先说说为什么我想要尝试着去搭建属于自己的Blog,古人云:“好记性不如烂笔头”.一开始我把笔记做在本子上.电脑上,发现要用的时候特别地不方便,而且越记越多.越多越 ...