比赛地址:
小白月赛66

A 先交换

如果第一个元素是奇数,那么无需操作,输出 0 。
如果第一个元素是偶数,且后面有元素比它小,且是奇数,输出 1 。
否则,输出 -1 。

#include <iostream>
using namespace std;
int a[110];
int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int t,n,i;
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(i=1;i<=n;++i)
			cin>>a[i];
		if(a[1]&1)
			cout<<"0\n";
		else
		{
			for(i=2;i<=n;++i)
				if((a[i]&1)&&a[1]>a[i])
					goto end;
			if(true)
				cout<<"-1\n";
			else
				end:cout<<"1\n";
		}
	}
	return 0;
}

B 再交换

逐位比较,分类讨论。
如果 a[i]==b[i] ,略过。
如果 a[i]>b[i] ,那么交换 a[i] 和 b[i] 即可。
如果 a[i]<b[i] ,那么交换 i+1 - n 之间的任意一对即可。
考虑到,可能没有 a[i+1] 和 b[i+1] ,可以单独拿出 a[0] 和 b[0] 进行讨论。
请注意,对于任意的 i>0 ,a[i]>b[i] 或者 a[i]<b[i] 都是基于 a[i-1]==b[i-1] 出现的。
举例:
3
4
1234
1235
4
2023
2022
3
123
321

#include <iostream>
#include <string>
using namespace std;
int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	string a,b;
	char c;
	int t,n,i,k;
	cin>>t;
	while(t--)
	{
		cin>>n>>a>>b;
		if(a[0]<b[0])
			cout<<"2 2\n";
		else if(a[0]>b[0])
			cout<<"1 1\n";
		else
		{
			for(i=1;i<=n;++i)
			{
				if(a[i]==b[i])
					continue;
				else if(a[i]>b[i])
					cout<<i+1<<' '<<i+1<<'\n';
				else
					cout<<"1 1\n";
				break;
			}
		}
	}
	return 0;
}

C 空洞骑士

假设终点是边界两端的其中一点,起点任意选择。
那么小骑士在最优情况下,会先去收集 离终点最远 的那个吉欧,然后再前往终点。
显然,起点和这个吉欧的距离,越大越好,要么是另一个端点,要么是终点旁边的那个点。
先定起点,再判断终点,也是如此。
另外,还有一个大保底,起点和终点分别是 0 和 1000000000 ,这样保证用时至少为 1000000000 。

#include <iostream>
using namespace std;
int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	long long ans=0,w;
	int m,n=0,i,k,x,y,m1=2e9,m2=-1;
	cin>>m;
	for(i=0;i<m;++i)
	{
		cin>>k;
		m1=min(m1,k);
        m2=max(m2,k);
	}
	if(m1==m2)
		cout<<"0 1000000000";
	else
	{
		w=m2*2-1;
		x=0;
		y=1;
		if((1000000000-m1)*2-1>w)
		{
			w=(1000000000-m1)*2-1;
			x=999999999;
			y=1000000000;
		}
		if(w<1000000000)
		{
			x=0;
			y=1000000000;
		}
		cout<<x<<' '<<y;
	}
	return 0;
}

D 障碍

如果移除一个障碍,并不能使最长段的长度 L 增加,那么这个操作是没有意义。
所以移除障碍时,必须是连续地移除,不然代价会让你自讨苦吃。
如果 L-x² 是负数,就没必要继续计算了。
因为最坏情况下,每一个坐标都有一个障碍,L=1 且 x=0 ,保底答案是 1 。
补两个端点 0 和 n ,这样就不用分类讨论。
剩下的工作,就是二重循环,枚举 a[j]-a[j-k] 。
更新 ans 的时候,再减去 i² ,减少耗时。

#include <iostream>
#include <algorithm>
using namespace std;
int a[100100];
int b[1010];
int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n,m,i,j,k,ans=1,s;
	cin>>n>>m;
	for(i=1;i<=m;++i)
		cin>>a[i];
	sort(a+1,a+m+1);
	for(i=1;i<1010;++i)
		b[i]=i*i;
    if(a[m]!=n)
        a[++m]=n;
	for(i=0;true;++i)
	{
		if(n<b[i])
			break;
		k=i+1;
		s=1;
		for(j=k;j<=m;++j)
			s=max(s,a[j]-a[j-k]);
		ans=max(ans,s-b[i]);
	}
	cout<<ans;
	return 0;
}

如有疑问,欢迎在评论区交流。