Codeforces Round 865 (Div. 2)

文章介绍了两道Codeforces平台上的编程问题,一题涉及如何处理数组使其非递减,另一题关注图的连通性。对于数组问题,解决方案是根据数组长度的奇偶性调整元素,确保至少n-1个数相等。对于图的连通性问题,策略是构建特定链并进行询问,以找到最小步数使所有点连通。
摘要由CSDN通过智能技术生成

Problem - C - Codeforces

思路:

  1. 我们最后需要处理数组是非递减的,我们可以尽量处理它相等(显然,至少可以使n-1个数相等)
  2. 当n是奇数时,我们显然可以凑出a1=a2=...a[n-1],然后比较a[n],因为前面有偶数个数,显然这偶数个数可以一起修改到比a[n]小。
  3. 当n是偶数时,我们怎么凑,如果最后是a1=a2=...a[n-1]>a[n],我们无法修改<变为>=,因为前面只有奇数个数,无法全部一起修改
#include <bits/stdc++.h>
using namespace std;
#define ll               long long
#define int ll
#define endl             "\n"
const int N = 3e5 + 10;
int a[N];
void mysolve()
{
	int n;
	cin>>n;
	for(int i=1; i<=n; ++i)cin>>a[i];
	if(n&1)cout<<"YES"<<endl;
	else
		{
			for(int i=1; i<n-1; ++i)
				{
					int tmp=a[i+1]-a[i];
					a[i+1]-=tmp,a[i+2]-=tmp;
				}
			if(a[n]>=a[n-1])cout<<"YES"<<endl;
			else cout<<"NO"<<endl;
		}
}

int32_t main()
{
	std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll t=1;
	cin >> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

Problem - D - Codeforces

思路:

  1. 我们希望询问的时候边都是连通的,不然返回-1就血亏。那么有没有最少的步骤使所有点连通。观察到n+1于n+2就可以使图连通。形成了1->n->2->n-1->n-2->3...这样的链
  2. 我们显然可以先询问p1到pi(1<i<=n)的距离,显然,距离最大的i(设为k)一定是链的端点
  3. 因此,我们接下来询问其他数pi到pk的距离,就可以凑出k在左端点时的答案与k在右端点时的答案,使用了2+(n-1)+(n-1)=2n的操作,刚刚好
#include <bits/stdc++.h>
using namespace std;
#define ll               long long
#define endl             "\n"
#define int              long long
const int N = 2e3 + 10;
int a[N];
void mysolve()
{
	int n;
	cin>>n;
	int p1=1,p2=n;
	for(int i=1; i<=n; i+=2)a[i]=p1++,a[i+1]=p2--;//构造链
	int x;
	char c='+';
	cout<<c<<" "<<n+1<<endl;
	cin>>x;
	cout<<c<<" "<<n+2<<endl;
	cin>>x;
	int k=1,p=0;
	c='?';
	for(int i=2; i<=n; ++i)
		{
			cout<<c<<" "<<1<<' '<<i<<endl;
			cin>>x;
			if(x>p)p=x,k=i;//找到端点k
		}
	vector<int>ans1(n+1),ans2(n+1);
	ans1[k]=a[1],ans2[k]=a[n];
	for(int i=1; i<=n; ++i)if(i!=k)
			{
				cout<<c<<" "<<k<<" "<<i<<endl;
				cin>>x;
				ans1[i]=a[1+x];//分别找出k在不同端点形成的序列
				ans2[i]=a[n-x];
			}
	cout<<"!";
	for(int i=1; i<=n; ++i)cout<<" "<<ans1[i];
	for(int i=1; i<=n; ++i)cout<<" "<<ans2[i];
	cout<<endl;
	cin>>x;
}

int32_t main()
{
	//std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll t=1;
	cin >> t;
	while (t--)
		{
			mysolve();
		}
//	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值