Educational Codeforces Round 123 (Rated for Div. 2)(A~C)

开学以后就忙起来了,cf勉强当天写题,题解都跟不上了~

A.  Doors and Keys

https://codeforces.com/contest/1644/problem/A

Question:

给定长度为6的字符串,有RGB三色的门,分别需要对应的钥匙rgb来打开,还有一个限定条件,主人公按照字符串的顺序去开门,只有打开一扇门之后才能去开下一扇门,问主人公最后能不能打开所有的门

Solve:

思路比较简单,从前到后读字符串,用cnt数组把现有的钥匙存下来,当遇到对应的门之后cnt--,把钥匙消耗掉,如果遇到对应的门没有钥匙,就标记下来退出循环

AC Code:

#include<bits/stdc++.h>
using namespace std;
int t;
string s; 
void solve()
{
	int cnt[30];
	memset(cnt,0,sizeof(cnt));
	cin >>s;
	for(int i = 0; i < 6; i++){
		//读入钥匙 
		if(s[i] == 'r' || s[i] == 'g' || s[i] == 'b') cnt[s[i] - 'a']++;
		else{
			//如果没有钥匙就输出NO 
			if(cnt[s[i] - 'A'] == 0) {
				cout <<"NO" <<endl;
				return;
			}
			else cnt[s[i] - 'A']--;
		}
	}
	cout <<"YES" <<endl;
}
int main(void)
{
	std::ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	
	cin >>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

B.  Anti-Fibonacci Permutation       

 https://codeforces.com/contest/1644/problem/B

Question:

反斐波那契数列,构造n个1~n的全排列a,使得任给一个i都满足a[i] != a[i-1] + a[i-2]

Solve:

构造方法很多,这个题我的第一反应是要想满足a[i] != a[i-1] + a[i-2],最简单的,前面的数比后面的数大,那就肯定不会满足这个条件

所以我就顺着这个思路,逆序输出1~n,但是题目要求是n个排列啊,又不是一个,然后怎么办呢

我直接将1~n先逆序,然后在把后面的小数去做交换,交换一次输出一次

比如n=5,就输出

54321

54312

54132

51432

15432

AC Code:

#include<bits/stdc++.h>
using namespace std;
int t, n;
int a[55];
void solve()
{
	cin >>n;
	for(int i = 1; i <= n; i++) a[i] = i;
	int pos = 1;
	//第一次的直接完全逆序输出 
	for(int i = n; i >= 1; i--) cout <<a[i] <<" ";
	cout <<endl;
	for(int i = 1; i <= n-1; i++){
		//交换元素输出n-1次 
		swap(a[pos], a[pos+1]);
		pos++;
		for(int j = n; j >= 1; j--){
			cout <<a[j] <<" ";
		}
		cout <<endl;
	}
}
 
int main(void)
{
	std::ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	
	cin >>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

C.  Increase Subarray Sums      

 https://codeforces.com/contest/1644/problem/C

Question:

先给一个长度为n的数组,然后题目想将给定的x插入数组的不同位置中

然后问你:当数组插入k个x(0 <= k <= n)时,其最大子列和是多少

Solve:

去掉插入x就是个dp基础题,虽然我不知道我但是为什么会想到模拟上,裂开

参考知乎pzr大佬的思路

max{ans[i] + min(i, k)*x} (0 <= i <= n)

首先去把原数组中选择i个连续元素的最大子列和存到ans[i]中

之后我要求添加k个x的最大子列和时,只要在ans数组中去找到ans[i]+min(i, k)*x的最大值即可,

min(i, k)是因为有i个元素的子列中最多只能添加i个x去使得子列和变大

AC Code:

代码也是借鉴pzr大佬的,前缀和数组我直接读入数据时候去维护了,max_element还是看了代码才了解的,哎,菜啊

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t, n, x;
//数据数组,前缀和数组,子列和数组 
ll a[5010], pre[5010], ans[5010]; 

void solve()
{
	cin >>n >>x;
	//计算前缀和 
    pre[0] = 0;
	for(int i = 1; i <= n; i++){
		cin >>a[i];
		pre[i] = pre[i-1] + a[i];	
	} 
	//初始化ans数组 
	for(int i = 1; i <= n; i++) ans[i] = -1e18;
	ans[0] = 0;
	//计算出i个元素构成的最大子列和ans[i] 
	for(int l = 1; l <= n; l++){
	    for(int r = l; r <= n; r++){
	        ans[r-l+1] = max(ans[r-l+1], pre[r] - pre[l-1]);
   		}
	}
	//输出k=0时的最大子列和 
    cout <<*max_element(ans,ans+1+n) <<" ";
    
    for(int i = 1; i <= n; i++){
        for(int j = 0; j <= n; j++){
            if(j >= i) ans[j] += x;
        }
        cout <<*max_element(ans,ans+1+n) <<" ";
    }
    cout <<endl;
}
int main(void)
{
	std::ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >>t;
	while(t--){
		solve();
	}
	return 0;
}

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UmVfX1BvaW50

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值