Codeforces 914(Div2) A-C

A

a题的思路就是直接暴力模拟出所有的可能性,这里可以用到在bfs求最短通路中的一种枚举形式.

#include<bits/stdc++.h>
using namespace std;
void solve()
{
	int a, b, x1, y1, x2, y2;
	cin >> a >> b >> x1 >> y1 >> x2 >> y2;
	int dx[8] = { a,-a,a,-a,b,-b,b,-b };
	int dy[8] = { b,-b,-b,b,a,-a,-a,a };//列举出一个点的八种可能性,就是这匹马的八个位置
	int ans = 0;
	for (int i = 0; i < (a == b ? 4 : 8); i++)//判断a,b是否相等,如果相等就只会有四种走法
	{
		int nx = x1 + dx[i];
		int ny = y1 + dy[i];
		if ((abs(x2 - nx) == a && abs(y2 - ny) == b) || (abs(x2 - nx) == b && abs(y2 - ny) == a))ans++;
	}
	cout << ans << '\n';
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int _; cin >> _;
	while (_--)solve();
}

本题我学会了什么:在类似有关到坐标系枚举的问题时,可以考虑用数组来模拟他的所有走法,然后进行判断.

B

题意:b题的题意也很好理解,就是选定一个数,然后其他数为一个数组,如果这个数大于其中某个数,就删去那个数,然后加到这个数上,最后要判断每个位置的数最多能删去多少个数.

分析:这个题目我们肯定是要排序的,但是最终结果输出又和下标有关系,毫无疑问,我们是要记录下标的,这个时候我们要考虑开一个结构体,同时规定一个cmp函数来说明排序顺序,在排序完后,我们就可以进行类似于双指针的操作

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 5;
struct point
{
	int idx;
	ll num;

}a[N];
int b[N];
bool cmp(point a, point b)
{
	return a.num < b.num;
}//cmp规定以num为判断的标准
void solve()
{
	int n; cin >> n;
	for (int i = 0; i <= n - 1; ++i)
	{
		cin >> a[i].num;
		a[i].idx = i;
	}
	sort(a, a + n, cmp);
	ll sum = 0;
	int j = 0;
	for (int i = 0; i <= n - 1; ++i)
	{
		while (j <= i)
		{
			sum += a[i].num;
			j++;
		}//因为a数组已经排序过,所以在i前面的数肯定小于a[i]无脑加上就行,最后答案也肯定会大于i-1
		while (j < n && sum >= a[j].num)
		{
			sum += a[j].num;
			j++;
		}//到这里就是判断a[i]后面那些比他本身要大的数了,这个时候就要考虑前面的和是否大于后面的数了
		b[a[i].idx] = j - 1;//b数组就是最后的答案,记得要按a[i]的下标来
	}
	for (int i = 0; i <= n - 1; ++i)cout << b[i] << ' ';
	cout << '\n';
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int _; cin >> _;
	while (_--)solve();
}

关键:对比ai大和比ai小的那些数分开进行讨论

C

我们可以知道,当k>=3时,就一定可以对同一对数进行两次操作,然后再把新产生的两个数进行操作来得到0,那么我们就只要讨论k==1和k==2的情况,k==1的情况其实很好讨论,就是开个ai-ai-1的数组,然后输出最小值就行了,而k==2需要我们进行遍历,并且在每一次遍历中去原数组中找到和新产生的数最相近的两个数,然后把他们的差值与原数组最小值以及他自身进行比较

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
	int n, k; cin >> n >> k;
	vector<ll>a(n);
	for (int i = 0; i <= n - 1; ++i)cin >> a[i];
	sort(a.begin(), a.end());
	if (k >= 3)
	{
		cout << 0 << '\n';
		return;
	}//若大于等于3,直接输出0即可
	else
	{
		ll mi = a[0];
		for (int i = 0; i <= n - 2; ++i)
		{
			mi = min((a[i + 1] - a[i]), mi);
		}//求出原数组中差值的最小值
		if (k == 1)
		{
			cout << mi << '\n';
		}
		else
		{
			for(int i=0;i<=n-1;++i)
				for (int j = 0; j <= n - 1; ++j)
				{
					if (i == j)continue;
					int idx = lower_bound(a.begin(), a.end(), abs(a[i] - a[j])) - a.begin();//lower_bound减去begin()函数来记录下标
					if (idx != n)mi = min(abs(a[idx] - abs(a[i] - a[j])), mi);
					if (idx != 0)mi = min(abs(abs(a[i] - a[j]) - a[idx - 1]), mi);//前面两个限制条件都是为了防止数组越界
					mi = min(abs(a[i] - a[j]), mi);
				}
			cout << mi << '\n';
		}
	}
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int _; cin >> _;
	while (_--)solve();
}

关键:本题难点在于分析k==2的情况,这时要注意他进行第二次操作时是对与ai相差最小的两个数进行计算,此时可以考虑用二分查找的lower_bound来返回下标,这题的最后就是对 ai-aj 与 ai-aj-a[idx]以及ai-aj-a[idx-1]三个数进行比较。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值