CF2277E Tree Guessing题解

CF2277E Tree Guessing

成功入选榜单前 10 10 10 qwq!

思路

为了方便表述,我们定义节点 i i i 的权值为 p i p_i pi,路径的权值为路径上所有节点的权值的最大值。

我们可以钦定树的根为 1 1 1,然后每次询问选择的顶点 x x x 也是 1 1 1,这样一来,每次询问得到的就是每个点到根节点的路径的权值之和。

考虑令根节点的权值为 n − 1 n-1 n−1,同时枚举 2 2 2 到 n n n 的节点 x x x,令 x x x 的权值为 n n n。这样一来,每次询问除经过节点 x x x 的路径外,其余路径的权值均为 n − 1 n-1 n−1,而经过节点 x x x 的路径数量为 x x x 的子树大小。于是我们可以通过 n − 1 n-1 n−1 次询问求出每个节点的子树大小。

考虑求出来子树大小有啥用?我们可以按照子树大小从大到小处理节点,求出每个节点的父亲。这样一来,处理到节点 x x x 时 x x x 的祖先一定全部处理好了。我们将节点 x x x 的权值赋值为 n n n,将所有已经处理好的节点(假设有 s i si si 个)赋值为 n − s i , n − 1 n-si,n-1 n−si,n−1,并且要求儿子节点的权值大于父亲节点的权值,其余的点随便赋。这样,假设不考虑节点 x x x 的时权值为 s u m 1 sum1 sum1,我们询问交互库给出的答案为 s u m 2 sum2 sum2, s u m 2 − s u m 1 sum2-sum1 sum2−sum1 形成的差值就是 s x × ( n − p f a x ) s_x \times(n-p_{fa_x}) sx×(n−pfax),可以求出 f a x fa_x fax。

恰好 2 n − 2 2 n-2 2n−2 次询问。

代码

时间复杂度 O ( n 2 ) O(n^2) O(n2)。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int t,n,p[505],si[505],fa[505];
long long qiu()
{
	cout<<"? 1 ";
	for(int i=1;i<=n;i++) cout<<p[i]<<" ";
	cout<<endl;
	long long x;
	cin>>x;
	return x;
}
pair<int,int> q[505];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		p[1]=n-1;
		for(int i=2;i<=n;i++)
		{
			p[i]=n;
			int cnt=0;
			for(int j=2;j<=n;j++)
				if(j!=i) cnt++,p[j]=cnt;
			si[i]=qiu()-(n-1)*1ll*n;
		}
		si[1]=n;
		for(int i=1;i<=n;i++) fa[i]=0;
		for(int i=1;i<=n;i++) q[i]={si[i],i};
		sort(q+1,q+1+n);
		for(int i=n-1;i>=1;i--)
		{
			int x=q[i].second;
			p[x]=n;
			for(int j=1;j<i;j++) p[q[j].second]=j;
			for(int j=n;j>i;j--) p[q[j].second]=n-1-(j-i-1);
			long long sum2=qiu(),sum1=0;
			for(int j=n;j>i;j--) sum1+=si[q[j].second]*1ll*p[q[j].second]-si[q[j].second]*1ll*p[fa[q[j].second]];
			fa[x]=q[i+(sum2-sum1)/si[x]].second;
		}
		cout<<"!"<<endl;
		for(int i=2;i<=n;i++) cout<<i<<" "<<fa[i]<<endl;
	}
	return 0;
}
相关推荐
逐光者9335 小时前
杨氏模量:从定义到工程应用
算法
syagain_zsx6 小时前
ODB 与 MySQL:C++ 里的 ORM 实践(类即表、事务铁律与查询封装)
开发语言·数据库·c++·mysql·工具库·1024程序员节
小鱼仙官6 小时前
使用Qt封装C/C++ 动态库 用于第三方调用
c语言·c++·qt
荆棘鸟智能6 小时前
扬尘在线监测数据接入与异常清洗:从断点补传到质量审计
人工智能·算法·系统架构
晚风予卿云月7 小时前
【C++高并发内存池】 1.定长内存池的实现
开发语言·c++·内存管理
动词ing7 小时前
【题目练习】旋转图像
算法
天疆说7 小时前
【无标题】
算法
CappuccinoRose7 小时前
滚动交互体系
前端·javascript·交互·html5·1024程序员节
GG.WinGel7 小时前
三元组中心问题
java·数据结构·算法·青少年编程·蓝桥杯