AtCoder_abc334

发布时间 2024-01-01 01:29:55作者: Tom-catlll

A、Christmas Present

跳转原题点击此:A题地址

1、题目大意

  给你bat和glove的价格,选择价格高的那个,并输出"Bat"或者"Glove"。

2、题目解析

  没啥好说的,直接比较即可,记得不要输错英文字母。

3、具体代码

#include<bits/stdc++.h>

using namespace std;

void solve()
{
	int a, b;
	cin >> a >> b;
	if(a > b)
		cout << "Bat";
	else
		cout << "Glove";
}

int main()
{
	solve();

	return 0;
}

 

B、Christmas Trees

跳转原题点击此:B题地址

1、题目大意

  在A点(A点设为原点,左边是x轴,右边是x轴)处沿着左右两边每m米设置一棵圣诞树(A点也要设置),然后问你在\(l \sim r\)(l 和 r 也包含在内)的区间设置了几棵圣诞树。

2、题目解析

  我们可以分类讨论(大佬都是通过数学公式推出来,我很菜不会):

  1. A点在区间内:就可以通过(左边的范围/m) + (右边的范围 / m) + A点本身(因为A点也要设置圣诞树);
  2. A点在区间左边:即(r 到 A的范围 / m + A点本身)- (l-1 到 A的范围 + A点本身);
  3. A点在区间右边:即(l 到 A的范围 / m + A点本身)- (r+1 到 A的范围 + A点本身)。

3、具体代码

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

ll a, m, l, r;

void solve()
{
	cin >> a >> m >> l >> r;
	ll ans = 0;
	// 如果a在l和r的中间
	if(l <= a && a <= r)
	{
		ans += (a - l) / m + 1;	// 加上a这个位置的本身
		ans += (r - a) / m;	// 重复就不用加了
	}
	// a在坐标轴左边
	else if(a < l)
	{
		ans += (r - a) / m + 1;
		ans -= ((l - 1) - a) / m + 1;
	}
	else if(a > r)
	{
		ans += (a - l) / m + 1;
		ans -= (a - (r + 1)) / m + 1;
	}
	cout << ans << endl;
}

int main()
{
	solve();

	return 0;
}

 

C、Socks 2

跳转原题点击此:C题地址

1、题目大意

  高桥有n双袜子,每双袜子的颜色都是不一样的且第i双袜子的颜色值为i。但是他突然遗失了k双袜子的一只袜子,使得k双袜子只有一只了。他想将剩下的袜子组成新的袜子并使得颜色差异值最小。并且当k为奇数时,会多出一只袜子。

2、题目解析

  我们发现,如果一双袜子没有遗失,那么它的差异值就为0。所以所以我们只需要对遗失一只袜子的k双袜子进行处理即可:
  当k为偶数时:差异最小化就是相邻的两只袜子配对;
  当k为奇数时,我们需要找到某一只袜子,使得其余袜子配对差异最小。所以我们只需要计算出第x只袜子的左右两边的前缀差异值即可,然后不断地比较找到差异值最小即可。

3、具体代码

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 2e5+10;
const int INF = 1e9 + 10;

int n, k;
int f[N];
int l[N], r[N];

void solve()
{
	cin >> n >> k;
	for(int i = 1; i <= k; i++)
		cin >> f[i];
	// 偶数袜子中,最好的结果就是两两相邻的袜子差异最小
	// 考虑奇数袜子中,需要去除一只袜子x:那么我们预先对x左边的差异和右边的差异做前缀和处理
	
	if(k & 1)	// 奇数双时
	{
		for(int i = 2; i <= k; i++)	// 左边的差异前缀和
		{
			// i-2 是因为,袜子是成对配的,所以a、b、c、d,我们算的是a、b 和 c、d的差异,而不是b、c的差异 
			l[i] = l[i - 2] + f[i] - f[i - 1];
		}
		for(int i = k - 1; i >= 1; i--) // 右边的差异前缀和
		{
			r[i] = r[i + 2] + f[i + 1] - f[i];
		}
	
		int ans = INF;
		// 先处理奇数双袜子
		for(int i = 1; i <= k; i+=2)	
		{
			// 如果不选第i只袜子,则计算i左边和右边的前缀和差异
			ans = min(ans, l[i - 1] + r[i + 1]);
		}
		cout << ans;
	}
	else	// 偶数双时
	{
		int ans = 0;
		for(int i = 1; i <= k; i+=2)
		{
			ans += (f[i + 1] - f[i]);
		}
		cout << ans;
	}
}

int main()
{
	solve();

	return 0;
}

 

D、Reindeer and Sleigh

跳转原题点击此:D题地址

1、题目大意

  给你n组雪橇,第i组地雪橇数量为\(a_i\)辆,并且每只驯鹿只能拉一辆雪橇。再给定q组询问:每次询问给你x只驯鹿,问你最多可以拉多少组雪橇。

2、题目解析

  要想拉的雪橇组最多,那么我们就需要从小到大排序,选择尽可能雪橇数量的x组雪橇。并且我们可以做前缀和来累加雪橇的数量(降低算法时间复杂度)。
  那么如何知道驯鹿能拉几组呢,通过二分查找来找到驯鹿所能拉的最大数量。

3、具体代码

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 2e5+10;

int n, q;
ll f[N], sum[N];


void solve()
{
	cin >> n >> q;
	for(int i = 1; i <= n; i++)
		cin >> f[i];

	// 注意先排序再求前缀和
	sort(f + 1, f + 1 + n);
	
	for(int i = 1; i <= n; i++)
		sum[i] = f[i] + sum[i - 1];
	
	while(q--)
	{
		ll x;
		cin >> x;
		// 通过二分查找答案
		int l = 0, r = n, ans;
		// 这里是普通二分,与学习的模板不太一样
		while(l <= r)
		{
			int mid = l + r >> 1;	// 往右找答案,即满足条件下选中最大的。
			// 如果 前mid辆雪橇 的重量 <= x,那么更新答案
			if(sum[mid] <= x)
			{
				ans = mid;
				l = mid + 1;	// 继续查找是否还有满足条件的
			}
			else
				r = mid - 1;	// 不满足条件,减少范围
		}
		cout << ans << "\n";
	}
	 
}

int main()
{
	solve();

	return 0;
}

 

E、F、G超出本人范围,以后再补上。