AcWing-周赛86

AcWing-周赛86

一、健身

【题目】

李华一共要进行n组健身训练。
其中,第i组训练的时长为ai
李华只做三种运动:胸部(chest)运动、二头肌(biceps)运动、背部(back)运动。
而且,三种运动是循环训练的,也就是说他第一组训练是胸部运动,第二组训练是二头肌运动,第三组训练是背部运动,第四组训练是胸部运动,第五组训练是二头肌运动…以此类推直到做完第n组训练。
请你计算,他做哪种运动的时长最长。
输入格式
第一行包含整数n。
第二行包含n个整数 a1,a2,…,an
输出格式
共一行,如果训练时长最长的运动为:
• 胸部运动,则输出 chest。
• 二头肌运动,则输出 biceps。
• 背部运动,则输出 back。
数据保证训练时长最长的运动是唯一的。
数据范围
前3个测试点满足 1≤n≤7。
所有测试点满足 1≤n≤20,1≤ai≤25。
输入样例1:
2
2 8
输出样例1:
biceps
输入样例2:
3
5 1 10
输出样例2:
back
输入样例3:
7
3 3 2 7 9 6 8
输出样例3:
chest

【解题思路】

模拟
三个数据一组:chest: i % 3 == 0;biceps: i % 3 == 1;back: i % 3 == 2;

【代码】

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
	int sum[3] = {0}; // 0-chest , 1-biceps , 2-back
	int n;
	cin >> n;
	for (int i = 0; i < n; i ++)
	{
		int a;
		cin >> a;
		sum[i % 3] += a;
	}
	int chest = sum[0] , biceps = sum[1] , back = sum[2] ;
	sort(sum , sum + 3);
	if (sum[2] == chest)  cout << "chest" ;
	else if (sum[2] == biceps)   cout << "biceps" ;
	else  cout << "back" ;
	return 0;
}

二、安全区域

【题目】

给定一个n×n的方格棋盘和m个国际象棋中的车。
对于一个方格,如果该方格满足以下两个条件中的至少一个,则该方格会被车攻击到:
• 该方格内有车。
• 至少有一个车与该方格位于同一行或同一列。
现在,我们要将m个车逐个放入到棋盘中,其中第i个车放到棋盘的第xi行第yi列的方格中。
车的编号从1到m,行/列的编号从1到n。
保证任意两个车不会放到同一个方格中。
对于1≤i≤m,请你计算,将前i个车放入到棋盘中后,有多少个方格不会被车攻击到。
输入格式
第一行包含两个整数n,m。
接下来m行,其中第i行包含两个整数xi,yi,表示第i个车放到棋盘的第xi行第yi列的方格中。
输出格式
在1行内输出m个数,其中第i个数表示将前i个车放入到棋盘中后,不会被车攻击到的方格数量。
数据范围
前3个测试点满足1≤m≤3。
所有测试点满足1≤n≤105,1≤m≤min(105,n2),1≤xi,yi≤n。
输入样例1:
3 3
1 1
3 1
2 2
输出样例1:
4 2 0
输入样例2:
5 2
1 5
5 1
输出样例2:
16 9
输入样例3:
100000 1
300 400
输出样例3:
9999800001

【解题思路】

类似于小学数学的面积平移的问题(在一个长方形花园中修路,求剩余面积的问题)。
令row = n ,col = n,输入一组x,y 就减一,不会被攻击的方格的数量=row×col。

注:若开一个105×105二维数组,数组会炸!!!

【代码】

#include <iostream>
#include <algorithm>
using namespace std;
bool a[100010] , b[100010] ;
int main()
{
	int n, m;
	cin >> n >> m;
	int row = n, col = n;
	while (m --)
	{
		int x, y;
		cin >> x >> y;
		if (!a[x])  a[x] = 1, row --;
		if (!b[y])  b[y] = 1, col --;
		cout <<(long long)row * col << ' ' ;
	}
	return 0;
}

三、删除序列

【题目】

给定一个长度为n的正整数序列a1,a2,…,an
你可以进行任意次删除操作。
每次删除操作分为两步:

  1. 选择序列中的一个元素(不妨设其元素值为x),并将这一个元素删除,这可以给你加x分。
  2. 将所有的元素值为x−1和x+1的元素(如果有的话)从序列中删除,这不会给你带来任何分数。
    请计算,通过删除操作,你可以获得的最大得分。
    输入格式
    第一行包含整数n。
    第二行包含n个正整数a1,a2,…,an
    输出格式
    一个整数,表示可以获得的最大得分。
    数据范围
    前6个测试点满足1≤n≤10。
    所有测试点满足1≤n≤105,1≤ai≤105
    输入样例1:
    2
    1 2
    输出样例1:
    2
    输入样例2:
    3
    1 2 3
    输出样例2:
    4
    输入样例3:
    9
    1 2 1 3 2 2 2 2 3
    输出样例3:
    10

【解题思路】

dp
最大收益→相同的数,要么全选,要么不选
设a[ i ]为所有数字i的价值,k个i→s[ i ] = k * i;
设f[ i ]为1至 i 获得的最大收益
状态转移方程:f[ i ] = max ( f[i – 1] , f[i – 2] + a[i] )

【代码】

#include <iostream>
using namespace std;
const int N = 100010;
long long a[N], f[N];
int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i ++ )
    {
        int x;
        cin >> x;
        a[x] += x;
    }
    f[1] = a[1];
    for (int i = 2; i <= 100000; i ++ )
        f[i] = max(f[i - 1], f[i - 2] + a[i]);
    cout << f[100000] ;
    return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值