AtCoder Regular Contest 142

32 篇文章 0 订阅
31 篇文章 0 订阅
本文详细介绍了两种算法问题的解决思路。一是如何构造一个满足特定条件的n阶矩阵,使得矩阵中每个元素的相邻元素大于它的数目与小于它的数目不相等;二是面对一个树型结构,如何通过询问节点间距离来高效地确定两个特定节点间的最短路径。文章通过实例分析和代码展示了解决这两个问题的具体步骤和技巧。
摘要由CSDN通过智能技术生成

A题不用说,C题之后不会。。。

B - Unbalanced Squares

大意:

构造一个n阶矩阵(元素从1~n^2),对于矩阵中的每一个元素,它周围的元素中大于它的数目和小于它的数目不能相等。

思路:
想了二十多分钟才有的思路。。。脑子是越来越不行了。

我的思路:

如果直接按从小到大的顺序做矩阵的话:

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

很明显是不行的。但是仔细观察一下,如果对每一行的元素改变一下顺序的话,可能是有希望的(总比全部重新构造好)。第一行和最后一行的每一个元素都是满足条件的。对于中间行的一些元素,如果它在边缘的话,下面两个元素是比它小的,上面两个元素是比它大的,那么旁边的元素无论是多少,都不会让这个元素不满足条件,所以两边的元素可以任意摆。剩余中间的,由于上面和下面的元素一样多,所以它两边的两个元素必须同时比它大或者同时比它小。

然后就可以随便试试了。

发现 a a+2 a+1 a+4 a+3 a+6 a+5...这个序列是ok的。

那么按规律填进去就可以了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define begin ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
ll n,t;
ll k;
void solve()
{
	cin>>n;
	if(n%2==1)
	{
		ll cnt=1;
		for(int i=1;i<=n;++i)
		{
			ll p=1+n*(i-1);
			if(i==1||i==n)
			{
				ll cnt=0;
				for(int j=1;j<=n;++j) cout<<p+(cnt++)<<' ';
				cout<<endl;
				continue;
			}
			cout<<p<<' ';
			ll cnt=1;
			for(int j=1;j<=(n-1)/2;++j)
			{
				cout<<p+(cnt)+1<<' '<<p+cnt<<' ';
				cnt+=2;
			}
			cout<<endl;
		}
		return;
	}
	else if(n%2==0)
	{
		ll cnt=1;
		for(int i=1;i<=n;++i)
		{
			ll p=1+n*(i-1);
			if(i==1||i==n)
			{
				ll cnt=0;
				for(int j=1;j<=n;++j) cout<<p+(cnt++)<<' ';
				cout<<endl;
				continue;
			}
			cout<<p<<' ';
			ll cnt=1;
			for(int j=1;j<=n/2-1;++j)
			{
				cout<<p+(cnt)+1<<' '<<p+cnt<<' ';
				cnt+=2;
			}
			cout<<p+cnt;
			cout<<endl;
		}
		return;
	}
	return;
}
int main()
{begin
	solve();
	return 0;
}

C - Tree Queries 

大意:

一道交互题(因为问问题的格式不对白瞎两发,shit。。。)

有一个n个节点的树。可以问不超过n*2个问题,每个问题可以问任意两个节点的距离(除了问1 ,2的距离)。

然后让你求1,2的距离。

思路:
既然可以问那么多问题,本着不要白不要的原则,就先把所有节点到1和2的距离都问出来,这样只需要2*n-4个问题。

然后分两种情况

1,2的距离为1:

看看是否有到1的距离为1且到2的距离为2的点,有的话标记f1,如果有到2的距离为1且到1的距离为2的点,就标记f2.

如果f1,f2都被标记了,有两种情况: 

那么只要对两个点询问一次距离,如果不是1的话,就可以说明1,2的距离为1了。

另外 ,如果f1,f2只有一个被标记了,也可以说明1,2的距离为1(自行理解)

 

对于剩余的大部分情况(1,2距离!=1)

只要对所有到1的距离为1的点求出它们到2的距离的最小值,加上一就可以了。

所以整体最多只要2*n-3次询问就能解决问题了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define ser ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const ll N=110;
ll n;
ll dis[N];
ll p[N];
ll k;
void solve()
{
	std::cin>>n;
	memset(p,0x3f,sizeof p);
	memset(dis,0x3f,sizeof dis);
	//cout<<"HBK"<<endl;
	for(int i=3;i<=n;++i)
	{
		std::cout<<"? "<<i<<" "<<2<<endl;
		std::cin>>k;
		dis[i]=k;
	}
	for(int i=3;i<=n;++i)
	{
		std::cout<<"? "<<i<<" "<<1<<endl;
		std::cin>>k;
		p[i]=k;
	}
	ll f1=0,f2=0;
	for(int i=3;i<=n;++i){
		if(p[i]==1&&dis[i]==2) f1=i;
		if(p[i]==2&&dis[i]==1) f2=i;
	}
	if(f1&&f2)
	{
		std::cout<<"? "<<f1<<' '<<f2<<endl;
		//cout<<"sdddddd"<<endl;
		std::cin>>k;
		if(k==1);
		else
		{
			cout<<"! "<<1<<endl;
			return;
		}
	}
	if((f2&&!f1)||(f1&&!f2))
	{
		cout<<"! "<<1<<endl;
		return;
	}
	ll ans=10000;
	for(int i=3;i<=n;++i)
	{
		if(p[i]==1)
		{
			ans=min(ans,dis[i]);
		}
	}
	std::cout<<"! "<<ans+1;
}
int main()
{//ser
	solve();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值