Educational Codeforces Round 149 (Rated for Div. 2)(A—D、F)

news2025/1/11 21:44:43

文章目录

  • A. Grasshopper on a Line
    • 1、问题
    • 2、分析
    • 3、代码
  • B. Comparison String
    • 1、问题
    • 2、分析
    • 3、代码
  • C. Best Binary String
    • 1、问题
    • 2、分析
    • 3、代码
  • D. Bracket Coloring
    • 1、问题
    • 2、分析
    • 3、代码
  • E. Playoff Fixing
    • 1、问题
    • 2、分析
    • 3、代码
  • F. Editorial for Two
    • 1、问题
    • 2、分析
    • 3、代码

A. Grasshopper on a Line

A. Grasshopper on a Line

1、问题

给定一个 n n n k k k n n n可以写作 m m m个数字的和,但是题目规定这些数字不能是 k k k的倍数。现在需要我们找最小的 m m m,同时输出这 m m m个数字。

2、分析

如果 n n n不是 k k k的倍数,这里可以直接输出 n n n,即 m = 1 m=1 m=1

如果 n n n k k k的倍数,说明我们需要将 n n n进行拆分。这里给定一个结论:对于该种情况下的任意数字 n n n,都只需要拆成两个数字。

证明:
因为 n n n k k k的倍数,我们可以假设 n = a ∗ k n=a*k n=ak

如果 a ≥ 2 a\geq 2 a2

那么我们可以令 p + q = a p+q=a p+q=a,则 n = ( p + q ) ∗ k = p ∗ k + q ∗ k n=(p+q)*k=p*k+q*k n=(p+q)k=pk+qk,此时我们可以让 a n s 1 = p ∗ k + 1 ans_1=p*k+1 ans1=pk+1, a n s 2 = q ∗ k − 1 ans_2=q*k-1 ans2=qk1,因为题目规定 k ≥ 2 k \geq 2 k2。所以构造后的 p p p q q q都不会是 k k k的倍数。

如果 a < 2 a < 2 a<2,即 a = 1 a=1 a=1,此时可以让 p = 1 , q = n − 1 p=1,q=n-1 p=1,q=n1即可。

3、代码

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

void solve()
{
	int n, k;
	cin >> n >> k;
	if(n % k != 0)
	{
		cout << 1 << endl;
		cout << n << endl;
	}
	else
	{
		cout << 2 << endl;
		int a = n / k;
		if(a == 1)
			cout << 1 << " " << n - 1 << endl;
		else
			cout << (a - 1) * k + 1 << " " << k - 1 << endl;
	}
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

B. Comparison String

B. Comparison String

1、问题

给定一个由 ′ < ′ '<' < ′ > ′ '>' >构成的字符串S,其中如果S[i]表示 ‘ > ‘ ‘>‘ >,则对应的a数组则需要满足: a [ i ] > a [ i + 1 ] a[i]>a[i+1] a[i]>a[i+1],现在请用最少的数字构造出a数组,输出不同数字的个数。

2、分析

在这里插入图片描述
根据上面的例子可以看出,如果’>‘或者’<'连续排列的时候,我们的元素个数就会递增。当出现与之相反的符号的时候,我们可以用刚刚出现的数字构造出来。

而通过上述样例不难发现这样一个规律。
'>‘和’<'分别对应一个最长的连续子串,长度分别记为 p p p q q q。那么答案就是: a n s = m a x ( p , q ) + 1 ans=max(p,q)+1 ans=max(p,q)+1

3、代码

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

void solve()
{
	int n;
	string s;
	cin >> n >> s;
	int ans = 0;
	for(int i = 0; i < n; i ++)
	{
		int j = i;
		while(j < n && s[j] == s[i])
			j ++;
		ans = max(ans, j - i);
		i = j - 1;
	}
	cout << ans + 1 << endl;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

C. Best Binary String

C. Best Binary String

1、问题

给定一个字符串,这个字符串是由1,0,?三个字符构成的,其中?部分我们可以填写0也可以填写1,每个?之间是独立的,即某个?的填写并不影响后续?的填写选择。现在我们需要给字符串中的每一个?赋值。得到一个 01 01 01串,那么对于该 01 01 01串可以进行如下操作:选择任意连续子串进行反转。多次操作后,可以将该字符串排列为一个非降序字符串。在这个过程中,会得到一个操作次数。现在我们需要输出一个最小操作次数的 01 01 01字符串。

2、分析

按照题目要求,经过多次操作后,我们的字符串会变成下面的样子:

在这里插入图片描述

也就是说,我们需要将所有的1放在一起,所有的0放在一起。
在这里插入图片描述
从上面这个例子看出,只要有非连续的1存在,我们就需要一次操作,即存在多少个连续的1的字串,就需要进行几次反转,所以 我们的目的就是尽量减少连续1子串的个数

从上面这个结论可以看出,只要是形如:“1???1” 的子串存在,中间的问号都需要写成数字1

如果是**“0???1"或者"1???0”**的话,中间的问号都填0或者都填1其实是无所谓的。那么我们可以规定如果开头是0,就都写0,如果开头是1,就都写1。这样做的目的是为了好写代码。

如果问号出现在开头"???0",如果是这种情况,则需要全写0。因为如果我们全写1的话,会导致1的子串增多。
如果开头是"???1"全写0或者全写1都不影响1子串的个数,可以规定写0。这样的话,我们就可以将开头的情况统一一下:都写0。

如果问号出现在结尾:“1???”,全写1即可
如果结尾是"0???"全写0即可。即开头是什么就写什么

因此,上面的所有情况都可以归结为下面的方法:

如果开头是?,就改成0,剩余?都和前一个字符一致即可。(可以按照上述的分类讨论自行验证)

3、代码

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;

void solve()
{
	string s;
	cin >> s;
	if(s[0] == '?')
		s[0] = '0';
	for(int i = 0; i < s.size() - 1; i ++)
		if(s[i + 1] == '?')
			s[i + 1] = s[i];
	cout << s << endl;	
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
		solve();
}

D. Bracket Coloring

D. Bracket Coloring

1、问题

给定一个括号序列,如果括号序列是能够匹配上的, 例如:“()()”,“(()())”,“((()))”,或者反转以后是能够匹配上的,例如:“)(”, “))((”,就叫做美丽的括号序列。

现在给我们随机的一个括号序列,我们需要给这个括号序列进行染色,相同颜色的括号需要组成一个美丽的括号序列。

现在需要我们输出需要的最少颜色以及染色的策略。如果不论怎么染色都无法构成美丽括号序列的话,就输出-1。

2、分析

因为括号要左右一一匹配,所以如果左括号的个数不等于右括号的个数,则不可能构造出来答案,直接输出-1。

如果左括号的个数等于右括号的个数,则一定可以构造出来。为什么呢?

对于任意1个左括号和右括号,“)(”,“()”,都是美丽的,所以最坏情况下,我们给每一对括号都染色,则就会出现 n 2 \frac{n}{2} 2n个美丽括号。所以一定有解。

在考虑完是否有解后,我们接下来考虑一下最优解如何构造。

这里还是先给出一个结论,再证明:颜色的个数要么是1个,要么是2个。

1个的情况很简单,如果输入的括号序列本身就是美丽的,则只需要染成1个颜色。

接下来看一下2个颜色的情况:
在这里插入图片描述
如果是上图的情况,则最少是两种颜色,无可厚非。
在这里插入图片描述
如果是左图的情况,可以将后面红色的括号统一为前面蓝色的括号。其余情况同理。

接下来的问题就是涂色的问题了。

对于括号匹配的问题,通常用栈来解决。我们将第一个括号放到栈里,如果出现和第一个括号相同的括号就放到栈里,如果出现与之匹配的括号,就从栈顶取出一个括号与之匹配,然后删除栈顶。

如果遇到了能够和栈中括号匹配的括号,但栈却为空,说明需要涂成另外一个颜色。最后栈中剩下的括号,也需要涂成另外的颜色。

3、代码

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;

void solve()
{
	int n; 
	string s;
	cin >> n >> s;
	int nums = 0;
	for(int i = 0; i < n; i ++)
		if(s[i] == '(')
			nums ++;
	if(2 * nums != n)
	{
		cout << -1 << endl;
		return;
	}
	string str = "";
	for(int i = n - 1; i >=0; i --)
		str.push_back(s[i]);

	vector<int>ans(n, 0);
	stack<pair<char,int>>stk1;
	for(int i = 0; i < n; i ++)
	{
		if(s[i] == s[0])
			stk1.push({s[i], i});
		else
		{
			if(stk1.empty())
				ans[i] = 2;
			else
			{
				auto t = stk1.top();
				stk1.pop();
				ans[t.second] = 1;
				ans[i] = 1;
			}
		}
	}
	while(stk1.size())
	{
		auto t = stk1.top();
		stk1.pop();
		ans[t.second] = 2;
	}
	int x = 0;
	
	for(int i = 0; i < n; i ++)
		x += ans[i];

	if(x == n || x == 2 * n)
	{
		cout << 1 << endl;
		for(int i = 0; i < n; i ++)
			cout << 1 << " ";
		cout << endl;
		return;			
	}
	
	cout << 2 << endl;
	for(auto x : ans)
		cout << x << " ";
	cout << endl;

}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

E. Playoff Fixing

E. Playoff Fixing

1、问题

2、分析

3、代码

F. Editorial for Two

F. Editorial for Two

1、问题

给定一个 n n n k k k,以及一个长度为 n n n数组。现在从 n n n个数中,挑出 k k k个数,称作个子序列。然后将这个子序列分成两部分,记作子序列1和子序列2。那么子序列1和子序列2都有一个对应的和。这两个和能够比较出一个最大值。现在我们要求的是最大值的最小值

2、分析

这里有一个很常用的套路,当题目中让我们求最大值的最小值或者最小值的最大值的时候,一般采用二分来解决。

我们这里二分最终的答案。

对于二分而言,难点在于 c h e c k check check函数的书写。

这道题中, c h e c k check check函数的作用是判断二分过程中的 m i d mid mid值是否合理。

在这里插入图片描述
那么这个挑出最多 k 1 k1 k1个数的过程,用到了反悔贪心,反悔贪心的思路就是当所选数字的和小于 m i d mid mid的时候,就尽可能多的选数字,当大于 m i d mid mid的时候,就删除选择数字中的最大值,目的是留出更大空间选择更多的数字,而这个选择最大值的过程可以用大根堆来优化。

除此以外,图中前缀后缀划分的位置是不确定的,所以我们需要枚举所有的划分位置,找到一个可行的方案。

因此,我们可以先利用反悔贪心先预处理出来所有的前缀后缀中最多选择的数字 k 1 , k 2 k1,k2 k1,k2。然后再枚举划分位置,判断是否存在一组 k 1 + k 2 ≥ k k1+k2 \geq k k1+k2k

复杂度为: O ( l o g ( s u m ) ∗ ( n l o g n + n ) ) = O ( l o g ( s u m )   n   l o g n ) O(log(sum)*(nlogn+n))=O(log(sum)\ n\ logn) O(log(sum)(nlogn+n))=O(log(sum) n logn)

3、代码

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;


bool check(int maxv, int n, vector<int>a, int k)
{
	vector<int>f(n + 1, 0), g(n + 1, 0);
	priority_queue<int>q, qq;
	int sum = 0;
	for(int i = 0; i < n; i ++)
	{
		if(sum + a[i] <= maxv)
		{
			sum += a[i];
			q.push(a[i]);
			f[i + 1] = f[i] + 1;
		}
		else
		{
			q.push(a[i]);
			sum += a[i];
			sum -= q.top();
			q.pop();
			f[i + 1] = f[i];
		}
	}
	sum = 0;
	reverse(a.begin(), a.end());
	for(int i = 0; i < n; i ++)
	{
		if(sum + a[i] <= maxv)
		{
			sum += a[i];
			qq.push(a[i]);
			g[i + 1] = g[i] + 1;
		}
		else
		{
			sum += a[i];
			qq.push(a[i]);
			sum -= qq.top();
			qq.pop();
			g[i + 1] = g[i]; 
		}
	}

	for(int i = 1; i <= n; i ++ )
	{
		if(f[i] + g[n - i] >= k)
			return true;			
	}
	return false;

}

void solve()
{
	int n, k;
	cin >> n >> k;
	vector<int>a(n);
	int sum = 0;
	for(int i = 0; i < n; i ++)
	{
		cin >> a[i];
		sum += a[i];
	}
	int l = 0, r = sum;
	while(l < r)
	{
		int mid = l + r >> 1;
		if(check(mid, n, a, k))
			r = mid;
		else
			l = mid + 1;
	}
	cout << l << endl;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/605161.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库期末复习(6)基于哈希和B+树的索引查询

免责声明 练习题没有答案 图片都是自己做的 仅供参考 可扩展哈希表和练习 笔记 数据库--- 索引结构 (2)--可扩展哈希表及增删查_旅僧的博客-CSDN博客 练习 首先默认 局部深度都是1 然后进行插入 之后分裂 按照课件上的操作进行。 线性哈希表

插入排序,选择算法与快速排序(c语言,Java语言)

插入排序 原理&#xff1a;从数组的第二个元素开始,将数组中的每一个元素按照&#xff08;升序或者降序&#xff09;规则插入到已排好序的数组中以达到排序的目的。 插入排序并不是将元素取出来&#xff0c;插入到合适位置&#xff0c;之后的元素的位置依次加一&#xff0c;而…

在职阿里8年,一个31岁女软件测试工程师的心声

简单的先说一下&#xff0c;坐标杭州&#xff0c;13届本科毕业&#xff0c;算上年前在阿里巴巴的面试&#xff0c;一共有面试了有6家公司&#xff08;因为不想请假&#xff0c;因此只是每个晚上去其他公司面试&#xff0c;所以面试的公司比较少&#xff09; 其中成功的有4家&am…

【STL】stack、queue基本使用和模拟实现

目录 前言 stack 接口介绍 模拟实现 queue 接口介绍 模拟实现 没有迭代器 deque介绍 前言 stack 和 queue 本质上是一种容器配接器&#xff0c;就像我们平时充电时使用的电源适配器&#xff0c;能够将电压转换成设备能够接受的程度。 其通过封装特定容器作为其底层…

我的测试之路:从入坑测试到月薪15k...

“干过保险卖过房&#xff0c;做过销售做过网管”这是我毕业后前两年的真实写照&#xff0c;因为所学网络安全专业不好找工作&#xff0c;毕业之后为了生活只能将就的干着这种门槛低的工作。后来一次同学聚会被同学带下坑后&#xff0c;正式转行软件测试。 刚入坑的两年&#…

【自动化测试实战】从 0 到 1 搭建 Dubbo 接口自动化测试

前言 1、Dubbo 接口自动化测试框架实现逻辑 2、框架具体功能 3、关键实践 3.1 下载 provider 的 jar 包&#xff0c;并代理声明 zookeeper 设置 3.2 邮件发送功能 3.3 封装 Dubbo 接口信息类 3.4 利用 JMeter 调用 provider 服务&#xff0c;并断言&#xff0c;邮件报警…

音视频基础及海思sample_venc解读

1、sample的整体架构 (1)sample其实是很多个例程&#xff0c;所以有很多个main (2)每一个例程面向一个典型应用&#xff0c;common是通用性主体函数&#xff0c;我们只分析venc (3)基本的架构是&#xff1a;venc中的main调用venc中的功能函数&#xff0c;再调用common中的功…

python基于DeeplabV3Plus开发构建裂缝分割识别系统,并实现裂缝宽度计算测量

在我之前的文章中已经有不少基于裂缝场景的数据开发构建的模型了&#xff0c;感兴趣的话可以自行移步阅读&#xff0c;如下&#xff1a; 《基于yolov5sbifpn实践隧道裂缝裂痕检测》 《基于YOLOV7的桥梁基建裂缝检测》 《水泥路面、桥梁基建、隧道裂痕裂缝检测数据集》 《基…

SpringBoot异步执行方法

1. 源码跟踪 1.简单描述 在SpringBoot2.0.9之前需要手动自定义线程池(如下2.1), 然后指定线程池的名称 SpringBoot2.0.9以及之前的版本,使用的线程池默认是SimpleAsyncTaskExcutor, , 之后的版本使用的是ThreadpoolTaskExecutor 并且不需要手动的创建当前线程池(但往往我们…

多线程基础(五)ThreadLocal与四种引用

一、ThreadLocal ThreadLocal&#xff1a;解决每个线程绑定自己的值&#xff0c;存放线程的私有数据。 public class ThreadLocalTest {public static ThreadLocal local new ThreadLocal();public static void main(String[] args) {if(local.get() null){local.set("…

加成序列 dfs 迭代加深 java

&#x1f351; 加成序列 满足如下条件的序列 X X X&#xff08;序列中元素被标号为 1 、 2 、 3 … m 1、2、3…m 1、2、3…m&#xff09;被称为“加成序列”&#xff1a; KaTeX parse error: Undefined control sequence: \[ at position 2: X\̲[̲1\]1KaTeX parse error…

一文读懂MVCC:数据库中的并发读写利器!

大家好&#xff0c;我是你们的小米&#xff0c;一个积极活泼、喜好分享技术的小伙伴。今天&#xff0c;我想和大家聊一聊数据库领域的一个重要话题——MVCC多版本并发控制。MVCC是MySQL和其他一些数据库系统中常用的并发控制技术&#xff0c;通过它&#xff0c;我们可以在高并发…

如何用 Python 实现所有算法?

学会了 Python 基础知识&#xff0c;想进阶一下&#xff0c;那就来点算法吧&#xff01;毕竟编程语言只是工具&#xff0c;结构算法才是灵魂。 新手如何入门 Python 算法&#xff1f; 几位印度小哥在 GitHub 上建了一个各种 Python 算法的新手入门大全。从原理到代码&#xff0…

milkV-duo的Linux的开发环境搭建

目录 写在前面 内核编译 烧录失败的示例&#xff08;这种情况下就和插上空卡一样) 进入系统 串口进入 SSH接入 写在前面 基本上大部分的问题都能在开源社区上得到答案,记录下我遇到的问题. 附上开源社区 MilkV Community 这里的引脚图和板子的丝印有点对不上&#xff…

竞赛中常用的Python 标准库

对竞赛中常用得标准库进行解析和给出代码模板 目录 1.functools 1.1 cmp_to_key 1.2 lru_cache&#xff08;记忆化存储&#xff0c;加快递归速度&#xff09; 2.collections 2.1 deque 2.1.1 单调对列实现 2.1.2 BFS广搜 3.sys 3.1 sys.maxsize 3.2 sys.exit() 3.…

使用python的plot绘制loss、acc曲线,并存储成图片

使用 python的plot 绘制网络训练过程中的的 loss 曲线以及准确率变化曲线&#xff0c;这里的主要思想就时先把想要的损失值以及准确率值保存下来&#xff0c;保存到 .txt 文件中&#xff0c;待网络训练结束&#xff0c;我们再拿这存储的数据绘制各种曲线。 其大致步骤为&#x…

代码自动生成工具——TableGo(实例演示)

一、常用的代码生成器工具介绍 在SpringBoot项目开发中&#xff0c;为了提高开发效率&#xff0c;我们经常需要使用代码自动生成工具来生成一些重复性的代码&#xff0c;比如实体类、DAO、Service、Controller等等。下面介绍几个常用的代码自动生成工具&#xff1a; ①、MyBat…

如何在Linux 启用组播

第一章: 前言 多播技术&#xff0c;也被称为“组播”&#xff0c;是一种网络通信机制&#xff0c;它允许一个节点&#xff08;发送者&#xff09;向一组特定的节点&#xff08;接收者&#xff09;发送信息。这种方式在网络编程中非常有用&#xff0c;因为它可以大大提高效率和…

深度学习(Pytorch):Softmax回归

Softmax简介 Softmax回归是一个用于多类分类问题的线性模型&#xff0c;它是从Logistic回归模型演变而来的。Softmax回归与Logistic回归类似&#xff0c;但是输出不再是二元的&#xff0c;而是多类的。Softmax回归引入了softmax激活函数来将输出转换为合理的概率分布。与线性回…

HCIE-Cloud Computing LAB备考--第五题:规划--Type13练习--记忆技巧+默写

对LLD表,交换机接口表,ensp配置进行练习,如下图,设置答案和空白表,进行默写,汇总自己的容易犯的错误 LLD表默写思路 交换机接口配置表默写思路 以Type3为例,同颜色复制即可,共用ST.P0是A25,ST.P2是A21,FS是ST.P0是A21,ST.P2是A21。 ensp配置默写思路 特点: 所…