第8次总结(整合)

之前几次的总结忘记写了,这次把之前的能写的都写在一起。


CF题目:

别骂了别骂了,真的很努力的在补题了。

CF分数:

1050

截止2022-05-10


感觉最近在算法方面有点懈怠,然后可能花太多精力在项目上了,结果检查一下发现项目问题有一大堆,最近项目可以先缓缓了,等把项目结构重新构建一下 、细节调整一下、BUG修一下,给看过之后确认没问题了再继续写。

最近把题目好好补一补,CF好好打一打。


接下来是我觉得写得出来的CF题解

具体思路


对于这道题,题目要求通过一系列规定的操作把一串长为n的数组变成单调不减数组,问能不能实现。

a[i + 1] >= a[i]

 规定的操作是:

选择两个下标i, j,使得a[i] = -a[i], a[j] = -a[j]

交换i和j下标所在位置的数的符号

要形成单调不减数组,我们可以发现,在一系列操作后,我们可以把数组中的符号任意排列

因此我们只要把原数组中的负号全部移动到左侧,正号全部移动到右侧,最后再遍历判断一下,就可以知道经过一系列操作后能不能形成一个单调不减数组。

题解代码(不最优)


GNU G++20 11.2.0(64 bit, winlibs)
#include <bits/stdc++.h>

#define ll long long

using namespace std;

int main() {
	int t;
	cin >> t;
	while(t --) {
		int n;
		cin >> n;
		ll a[n + 1] = {0};
		int negative = 0;
		int positive = 0;
		for(int i = 0;i < n;i ++) {
			cin >> a[i];
			if(a[i] > 0) {
				positive ++;
			}
			else if(a[i] < 0) {
				negative ++;
			}
			a[i] = abs(a[i]);
		}

		for(int i = 0;i < negative;i ++) {
			a[i] = -a[i];
		}

		bool flag = true;
		for(int i = 0;i < n - 1;i ++) {
			if(a[i] > a[i + 1]) {
				flag = false;
				break;
			}
		}
		if(flag) {
			cout << "YES" << endl;
		} else {
			cout << "NO" << endl;
		}
	}
	return 0;
}

 

 具体思路


这道题目比较简单,就是猫粮、狗粮、通用粮食够不够宠物吃。

思路就是把狗粮和猫粮先全部专项供给,不够的再用通用粮食供给。

最后看看有没有剩下来的宠物还没吃的就可以了

题解代码(不最优)


 
#include <bits/stdc++.h>

#define int long long

using namespace std;

main() {
	int t;
	cin >> t;
	while(t --) {
		int a, b, c, x, y;
		cin >> a >> b >> c >> x >> y;
		x -= a;
		y -= b;
		if(x > 0) {
			if(c > x) {
				c -= x;
				x = 0;
			} else {
				x -= c;
				c = 0;
			}
		}
		if(c > 0 && y > 0) {
			if(c > y) {
				c -= y;
				y = 0;
			} else {
				y -= c;
				c = 0;
			}
		}
		bool flag = true;
		if(x > 0 || y > 0) flag = false;
		if(flag) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
}

具体思路


题目要求我们把一个长为n的数组通过一系列规定的操作变成单调严格递增的,问能不能实现,如果能输出最小操作次数,如果不能则输出-1。

即:

a[i + 1] > a[i]

规定的操作:

选定下标为i的值,对它进行向下取除以2的操作(5 / 2 = 2.5取2,8 / 2 = 4取4)

若要形成严格递增的数组,我们可以这么做:

暴力模拟,从下标n-1开始,对它除以2直到小于i + 1下标值。

注意退出条件,如果发现还没到开头都除到0了,那么它肯定没法形成严格递增的数组的。

题解代码(不最优)


#include <bits/stdc++.h>

#define int long long

using namespace std;

main() {
	int t;
	cin >> t;
	while(t --) {
		int n;
		cin >> n;
		int a[n];
		for(int i = 0;i < n;i ++) {
			cin >> a[i];
		}
		int cnt = 0;
		for(int i = n - 2;i >= 0;i --) {
			while(a[i] >= a[i + 1] && a[i] != 0) {
				a[i] /= 2;
				cnt ++;
			}
			if(a[i] == 0 && a[i] >= a[i + 1]) {
				cnt = -1;
				break;
			}
		}
		cout << cnt << endl;
	}
}

 

具体思路


这道题要找出一串字符中“可疑”的字符数量。

根据题目可知,可疑的人偷走了画,可疑的人可以选择撒谎(1/0/?),而其他人说的都是实话。我解题的办法比较“暴力”。

根据事实逻辑,我们可以分几种情况考虑:

(1) 1110000 [10/01交界类型]

(2) ????? [全问号型]

(3) 1?1??0?0 [1?0模糊边界型]

(4) 0?0??? [0开头型]

(5) ??11 [前导1结尾1型]

(6) ??0?? [模糊夹层0型]

(7) ??1?? [模糊夹层1型]

可知:

(1) 10交界有人说了假话,可疑的人数为2

(2) 不知道谁说了假话,所有人都可疑

(3) 1和0之间以及包含边界区间有人说了假话,可以人数为区间长度

(4) 0开头,无论真话假话他都是唯一嫌疑人

(5) 前面都是真话,最后画不见了,最后说还在的(说是1的)就是唯一嫌疑人

(6) 说0的可以为嫌疑人,其前导的模糊答案也都可以为嫌疑人,长度为0到开头的区间长度

(7) 说1的可以为嫌疑人,其后方的模糊答案也都可以为嫌疑人,长度为1到末尾的区间长度

具体逻辑可以自行分析

题解代码(不最优)


#include <bits/stdc++.h>

using namespace std;

main() {
	int t;
	cin >> t;
	while(t --) {
		string str;
		cin >> str;
		int len = str.size();
		if(len == 1 || str[0] == '0' || str[str.size() - 1] == '1') {
			cout << "1" << endl;
			continue;
		}
		int f1 = -1, f0 = -1;
		for(int i = 0;i < len;i ++) {
			if(str[i] == '1') f1 = i;
			else if(str[i] == '0' && f0 == -1) f0 = i;
		}
		if(f1 == -1 && f0 == -1) {
			cout << str.size() << endl;
		} 
		else if(f1 == -1 && f0 != -1) {
			cout << f0 + 1 << endl;
		}
		else if(f1 != -1 && f0 == -1) {
			cout << str.size() - f1 << endl;
		}
		else {
			cout << f0 - f1 + 1 << endl;
		}
	}

}

具体思路


这题要求我们把一个长为n的数组通过一系列规定操作变成全部为0的数组,问最少的操作次数。

规定操作:

选择两个下标i,j,进行如下操作

        如果a[i] = a[j],则其中一项变为0

        如果a[i] = a[j],则a[j] = a[i],反之亦然

对于这个问题,我们分几种情况:

(1) 1 2 3 4 5 全部都不一样

(2) 1 1 3 4 5 有至少1对一样

(3) 0 1 3 4 5 有0,没有相同对

(4) 0 1 1 4 5 有0,有相同对

可知

(1) 操作次数为n + 1

(2) 操作次数为n + 1 - 1 = n

(3) 操作次数为n + 1 - (0的个数 * 1 + 1) = n - (0的个数)

(4) 操作次数为n + 1 - 1 - (0的个数 * 1 + 1) + 1 = n - (0的个数)

这个情况下,只要有0,不论有没有相同对,操作次数都是剩下的不是0的元素的个数,如果没有0有相同对,那么操作次数就是n。

题解代码(不最优)


 

#include <bits/stdc++.h>

using namespace std;

int main() {
	int t;
	cin >> t;
	while(t --) {
		int n;
		bool vis[101];
		memset(vis, false, sizeof(vis));
		cin >> n;
		bool same = false;
		bool haveZero = false;
		int cnt = n + 1;
		for(int i = 0;i < n;i ++) {
			int tmp;
			cin >> tmp;
			if(vis[tmp] && !same) {
				cnt --;
				same = true;
			}
			vis[tmp] = true;
			if(tmp == 0) {
				cnt --;
				haveZero = true;
			}
		}
		if(haveZero && same) cnt ++;
		if(haveZero ) {
			cnt --;
		}
		cout << cnt << endl;
	}
	return 0;
}

 

具体思路


这道题有两个版本,这个是困难版,多个最小连续段数量的输出

这道题要求我们把一串由0和1构成的字符串变成偶数段+偶数段的形式

问要操作的最小字符个数以及最小连续段数量

1110001010 -> 1111000000

 成双搭配

既然两两搭配,那么我们遍历时就两个两个比较

遇到两个不一样的,就把需要搭改变的字符数量+1。因为变成什么样子不确定,所以我们可以把这两个字符变成通配符(即10,01变成22,记22为通配符),用于后面的最小连续段数量的计算。

在遍历完取得最小改变字符数量后,我们也取得了有通配符的字符串,再遍历一遍获得段个数即可。这里我使用了stack来存不同段,也可以使用其他方法统计。

题解代码

 

 


#include <bits/stdc++.h>

using namespace std;

int main() {
	int t;
	cin >> t;
	while(t --) {
		int n;
		cin >> n;
		int len = n;
		string str;
		cin >> str;
		int mincnt = 0;
		char last = '-';
		stack<char> stk;
		for(int i = 0;i < len;i += 2) {
			if(str[i] != str[i + 1]) {
				str[i] = '2';
				str[i + 1] = '2';
				mincnt ++;
			} else {
				if(str[i] != '2') {
					if(last == '-') {
						last = str[i];
						stk.push(str[i]);
					} else {
						if(last != str[i]) {
							stk.push(str[i]);
							last = str[i];
						} else {
							
						}
					}	
				}

			}
		}
		int pcnt = stk.size();
		if(stk.size() == 0) {
			pcnt = 1;
		}
		cout << mincnt << " " << pcnt << endl;
	}
	return 0;
}

题解结束,接下来是反思和计划


项目方面存在不足:

  1. 项目文件分包出现问题,分包不明确,出现错误,需要修正

  2.  客户端和服务端之间的逻辑仍存在部分问题,部分计划存在逻辑问题,需要修改。如客户端的被动接受(BIO)和通信问题。

  3. 已经实现的部分功能有问题。邮箱注册方面,发送邮箱验证码本地未实现倒计时,邮箱验证码不存在时限限制,需要修改。好友添加方面,接受好友和搜索好友列表存在BUG未刷新,需要修改。

  4. 数据库建表不完善,先完善数据库表再进行下一步编写。

  5. 项目面向对象编程没做到位。

算法方面存在不足:

  1. 过于懈怠,CF比赛刷题和补题不及时、积极性不高,导致水平徘徊不进。

  2. 补题过于一根筋,题解、答案理解不到位。 

其他方面存在不足 :

  1. 没有规划好时间,时间倾斜不到位。

  2. 没有计划好工作,资料搜集、归类、学习不到位。


计划:

  1. 接下来1周解决项目存在问题,主要是结构修改,暂不添加新内容
  2. 接下来1周把CF好好打打,题目尽快补完,努力提高积极性
  3. 重新规划时间,合理分配项目和算法的时间投入
  4. 询问资料,归类资料并学习,根据相关资料推进项目进度
  5. 学习他人经验,提升工作效率

项目概览:

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ISansXI

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

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

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

打赏作者

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

抵扣说明:

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

余额充值