【AtCoder Beginner Contest 261 (A·B·C·D)】

本文介绍了四道编程竞赛题目,包括区间染色问题、锦标赛结果验证、字符串处理及硬币翻转优化策略。通过暴力枚举、矩阵校验、计数统计及动态规划等方法,解析解题思路,并给出了C++代码实现,帮助读者提升算法思维和编程技巧。
摘要由CSDN通过智能技术生成

更好的阅读体验 \color{red}{更好的阅读体验} 更好的阅读体验



A - Intersection


题目大意

Originoal Link

给定两个染色区间的端点 L 1 , R 1 , L 2 , R 2 L_1,R_1,L_2,R_2 L1,R1,L2,R2,求同时染上两种颜色的区间长度


思想

  • 数据范围小,暴力枚举区间
  • 遍历两个区间,用res[i]记录被染色的情况
  • 遍历染色后的区间,计算区间长度

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 10;

int res[N];

int main(){
	
	int a, b, c, d;
	
	cin >> a >> b >> c >> d;
	
	for(int i = a; i <= b; i ++) res[i]++;
	
	for(int i = c; i <= d; i ++) res[i]++;
	
	int cnt = 0;
	for(int i = 0; i <= 200; i ++) if(res[i] == 2) cnt++;
	
	if(cnt) cout << cnt - 1 << endl;
	else cout << 0 << endl;
	
	return 0;
	
}

B - Tournament Result


题目大意

Origional Link

给定 N × N N\times N N×N的表,单元 A i , j A_{i,j} Ai,j记录了+ i i i j j j的对局输赢平的三种情况,若记录有冲突说明该表不正确


思想

  • 遍历表格,遍历 i i i行,每一行从 j = i + 1 j = i + 1 j=i+1列开始
  • 判断 A i , j A_{i,j} Ai,j A j , i A_{j,i} Aj,i的记录是否符合事实
  • 不符合事实进行标记并退出

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1010;

char mp[N][N];

int n;

int main(){
	
	cin >> n;
	
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= n; j++) cin >> mp[i][j];
	}
	
	bool flag = 1;
	for(int i = 1; i <= n; i ++){
		for(int j = i + 1; j <= n; j ++){
			if(mp[i][j] == 'D' && mp[j][i] != 'D'){
				flag = 0;
				break;
			}
			else if(mp[i][j] == 'W' && mp[j][i] != 'L'){
				flag = 0;
				break;
			}
			else if(mp[i][j] == 'L' && mp[j][i] != 'W'){
				flag = 0;
				break;
			}
		}
		if(!flag) break;
	}
	
	if(flag) cout << "correct" << endl;
	else cout << "incorrect" << endl;
	
	return 0;
	
}

C - NewFolder(1)


题目大意

Origional Link

给定 N N Nstring类型的 S S S串,按照给出 S S S的顺序,对于总共出现过 m m m S i S_i Si,若当前的 S i S_i Si第一次出现,输出 S i S_i Si,否则输出 S i ( u − 1 ) S_i(u-1) Si(u1) u u u表示第几次出现


思想

  • string s[N]存储读入 S S S的顺序
  • map<string,int> a,进行记录当前的 S i S_i Si出现了多少次
  • 遍历s[N],使得a[s[i]]++,若a[s[i]] - 1 == 0说明是第一次出现

代码

#include <bits/stdc++.h>
using namespace std;

map<string,int> a;

int n;

const int N = 1e6 + 3;

string s[N];

int main(){
	
	cin >> n;
	
	for(int i = 0; i < n; i ++) cin >> s[i];
	
	for(int i = 0; i < n; i ++){
		
		a[s[i]]++;
		int t = a[s[i]] - 1;
		if(t != 0){
			cout << s[i] << '(' << t << ')' << endl;
		}
		else cout << s[i] << endl;
		
	}
	
	return 0;
	
}

D - Flipping and Bonus


题目大意

Origional Link

投掷硬币为正面,计数器增加,反之计数器清零,给定 N N N次投掷硬币为正面得到的钱 X i X_i Xi,给定 M M M个奖励规则,若计数器的数值达到 C i C_i Ci,将获得 Y i Y_i Yi的奖励,求如何使得得到的钱最多


思想

  • a[N]记录 X i X_i Xib[N]记录 Y i Y_i Yi
  • 状态表示:dp[i][j]表示前i次投掷,当前计数器值为j时得到的钱
  • 状态计算:
    • 若投掷结果为正:则dp[i][j] = dp[i - 1][j - 1] + a[i] + b[j]
    • 反之计数器清零,更新之后的结果:dp[i][0] = max(dp[i][0],dp[i - 1][j])
  • 注意开long long

代码

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

LL n,m;

const LL N = 5010;

LL dp[N][N];

LL a[N];
LL b[N];

int main(){
	
	cin >> n >> m;
	
	for(int i = 1; i <= n; i ++) cin >> a[i];
	
	for(int i = 0; i < m; i ++){
		int x, y;
		cin >> x >> y;
		b[x] = y;
	}
	
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= i; j ++){
			dp[i][j] = dp[i - 1][j - 1] + a[i] + b[j];
		}
		
		for(int j = 0; j < i; j ++){
			dp[i][0] = max(dp[i][0],dp[i - 1][j]);
		}
		
	}
	
	LL ans = 0;
	
	for(int i = 0; i <= n; i ++) ans = max(ans,dp[n][i]);
	
	cout << ans << endl;
	
	return 0;
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

浪漫主义狗

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

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

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

打赏作者

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

抵扣说明:

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

余额充值