本周学习总结22.3.28-4.3:排序、stl、比赛

本周看了大概30余篇文章,并没有完成任务,是因为确实有很多文章我的水平是看不懂的,我也尽量多看一些文章。本周主要看的还是STL、排序以及搜索方面的,STL和排序的文章我能看懂绝大部分,虽然有些知识点记不住,但是看别人写的代码能明白他的思路,我也尽量多学多记。

在阅读STL方面的文章的时候,迭代器还是不太明白是什么东西,做的题大多还是STL有关的题,《算法笔记》这本书附带的网站上面有很多题,我大部分的题都是做的那个上面的。洛谷我也做了些题,但是自我感觉难度有点大,好多题都做不出来,甚至说是没有思路,看题解都看不懂,就比如这个题:

题目描述

所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。

如:3*(5–2)+7对应的后缀表达式为:3.5.2.-*7.+@。’@’为表达式的结束符号。‘.’为操作数的结束符号。

 题解说这个题用栈就能做出来,但是我一直很不理解这个题中,计算符号在计算时的先后顺序如何搞定,比如题目中的例子,他将5-2看成了一个整体,这就让我没有思路继续往下推进了。

周二晚上在做排序类型的题的时候,遇到一道特别好的题,这个题让我用了十几种排序的方法才ac出来,这个题本来是一道很简单的题,结果我小题大做,绕了一个很大的弯才做出来。题目如下:

利用快速排序算法将读入的 N 个数从小到大排序后输出。

题目很短,看起来也挺简单的(实际上确实挺简单)但是这个题却难住了我(题目禁止使用sort函数),我刚开始看到这个题,感觉用普通的排序就能做出来 ,我便用下述方式写了第一版代码:

#include<iostream>
#include<set>
#include<cstdio>
using namespace std;
int main() {
	int n, k, index;
	cin >> n ;
	set<int>a;
	for (int i = 1; i <= n; i++) {
		cin >> index;
		a.insert(index);
	}
	int add = 0;
	for (set<int>::iterator it = a.begin(); it != a.end(); it++) {
		printf("%d ", *it);
	}
}

用set自动排序直接输出,我把问题想得太简单了还是,最终只得了20分,我感觉我自己对set掌握的还不熟悉,迭代器之类的还是不熟练,最终导致只得二十分的原因至今我还是没有研究明白,我思考了一会之后,我换了下一种方式:

#include<iostream>
using namespace std;
int main() {
	int n, index;
	cin >> n;
	int a[100000];
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i < n; i++) {
		for (int j = i + 1; j <= n; j++) {
			if (a[i] > a[j]) {
				index = a[j];
				a[j] = a[i];
				a[i] = index;
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		cout << a[i] << " ";
	}
}

这个我用了最原始的方式,两个for循环,如果左边比右边大,就将两者调换,这个我也知道有一个致命的问题:超时,但我心怀侥幸心理,决定试一试,最终结果还是20分,没有通过的测试点都是因为超时了。

而后我又用了许许多多的办法,比如说:每次筛选出数组里最大的元素,把该元素堆到栈里,直至将最小的元素堆到里面,然后依次读取栈顶的元素,读取完接着pop掉,这样输出的也是从小到大排序的,使用queue也能做出来,但是很奇怪的是仍然满分不了,让我很是迷茫。

最后,我用multiset终于满分做出来了,而且特别特别简单,代码如下:

#include<iostream>
#include<cstdio>
#include<set>
using namespace std;
int main() {
	int n, index;
	cin >> n;
	int a[100000];
	multiset<int>s;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		s.insert(a[i]);
	}
	for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
		printf("%d ", *it);
	}
}

输入,再输出,完事儿,满分。

今天在codeforce上打了一场比赛,最终只AC了两道题,打完比赛后我总结了一下,做用到排序的题目中,最简洁&&最简单不易出错的方法就是Victor动态数组了,比赛中有一个题用到了排序,我尝试了数组、multiset、stack等等好几种方法,提交之后总会报超时,最终我用Victor+sort函数把题做对了(数组+sort函数居然也会超时这让我百思不得其解)。

这次codeforce比赛还有一个挺简单的题,让我仅用一个for循环就做出来了。

本周我主要是学了stl和排序,以及两种搜索,看博客也是主要看这几种的,之前的时候一直弄不明白迭代器是什么、怎么用。

B. Vlad and Candies

time limit per test:1 second

memory limit per test:256 megabytes

input:standard input

output:standard output


Not so long ago, Vlad had a birthday, for which he was presented with a package of candies. There were nn types of candies, there are aiai candies of the type ii (1≤i≤n1≤i≤n).

Vlad decided to eat exactly one candy every time, choosing any of the candies of a type that is currently the most frequent (if there are several such types, he can choose any of them). To get the maximum pleasure from eating, Vlad does not want to eat two candies of the same type in a row.

Help him figure out if he can eat all the candies without eating two identical candies in a row.

Input

The first line of input data contains an integer tt (1≤t≤1041≤t≤104) — the number of input test cases.

The following is a description of tt test cases of input, two lines for each.

The first line of the case contains the single number nn (1≤n≤2⋅1051≤n≤2⋅105) — the number of types of candies in the package.

The second line of the case contains nn integers aiai (1≤ai≤1091≤ai≤109) — the number of candies of the type ii.

It is guaranteed that the sum of nn for all cases does not exceed 2⋅1052⋅105.

Output

Output tt lines, each of which contains the answer to the corresponding test case of input. As an answer, output "YES" if Vlad can eat candy as planned, and "NO" otherwise.

You can output the answer in any case (for example, the strings "yEs", "yes", "Yes" and "YES" will be recognized as a positive answer).

 这个题我提交了四次都是超时,在第五次用了vector才ac,第一次我是直接用for循环挨个遍历求出答案,for循环多了,就会导致超时(用了四个循环不超时才怪呢)。代码如下:

#include<iostream>
using namespace std;
int main() {
	int t;
	cin >> t;
	for (int tt = 1; tt <= t; tt++) {
		int a;
		cin >> a;
		int n[2001], k[2001], maxx = 0;
		for (int i = 1; i <= a; i++) {
			cin >> n[i];
			k[i] = n[i];
			if (n[i] > maxx)maxx = n[i];
		}
		if (a == 1 && n[1] != 1) {
			cout << "NO" << endl;
			continue;
		}
		for (int i = 1; i <= a; i++) {
			if (k[i] == maxx) {
				k[i] = 0;
				break;
			}
		}
		int maxxx = 0;
		for (int i = 1; i <= a; i++) {
			if (k[i] > maxxx)maxxx = k[i];
		}
		if (maxx - maxxx == 1|| maxx - maxxx == 0) {
			cout << "YES" << endl;
		}
		else {
			cout << "NO" << endl;
		}
	}
}

然后我优化代码,尝试用multiset,这个有一个优点是能够自己排序,我本以为这样就不会超时了,但是很奇怪的是,我也很不理解,可能是我学习太欠缺了,还没有学的很深,这次第二个节点就超时了,甚至比for用的时间都长,看来我还是需要下功夫研究研究了。

#include<iostream>
#include<set>
#include<cstdio>
#include<algorithm>
using namespace std;
int main() {
	int t;
	cin >> t;
	for (int tt = 1; tt <= t; tt++) {
		int n;
		cin >> n;
		multiset<int>a;
		for (int i = 1; i <= n; i++) {
			int index;
			cin >> index;
			a.insert(index);
		}
		if (n == 1 && *a.rbegin() != 1) {
			cout << "NO" << endl;
			a.clear();
			continue;
		}
		if (n == 1 && *a.rbegin() == 1) {
			cout << "YES" << endl;
			a.clear();
			continue;
		}
		int max1 = *a.rbegin();
		a.erase(*a.rbegin());
		int max2 = *a.rbegin();
		if (max1 - max2 == 1|| max1 - max2 == 0) {
			cout << "YES" << endl;
		}
		else {
			cout << "NO" << endl;
		}
		//cout << max1 << " " << max2 << endl;
		a.clear();
		//cout << *a.rbegin() << endl;
	}
}

 然然后,我又又优化代码,这次我想起来了还有一个sort函数没用过,我又找到了第一版代码,排序的时候 我直接用sort函数,最后还是卡在了第四个测试点,依旧是超时。

#include<iostream>
#include<set>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int main() {
	int t;
	cin >> t;
	for (int tt = 1; tt <= t; tt++) {
		int n;
		cin >> n;
		int a[20000];
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
		}
		if (n == 1 && a[1] != 1) {
			cout << "NO" << endl;
			continue;
		}
		if (n == 1 && a[1] == 1) {
			cout << "YES" << endl;
			continue;
		}
		sort(a, a + n+1);
		int max1 = a[n];
		int max2 = a[n - 1];
		if (max1 - max2 == 1 || max1 - max2 == 0) {
			cout << "YES" << endl;
		}
		else {
			cout << "NO" << endl;
		}
		//cout << max1 << " " << max2 << endl;
		//cout << *a.rbegin() << endl;
	}
}

距离比赛结束仅剩20分钟的时候,我想到了用vector+sort解决问题的方法,这也应该大概或许是我能想到的最后的方法了,功夫不负有心人,这次是终于ac了。

#include<iostream>
#include<set>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	for (int tt = 1; tt <= t; tt++) {
		int n;
		cin >> n;
		vector<int> a;
		for (int i = 0; i < n; i++) {
			int index;
			cin >> index;
			a.push_back(index);
		}
		if (n == 1 && a[0] != 1) {
			cout << "NO" << endl;
			a.clear();
			continue;
		}
		if (n == 1 && a[0] == 1) {
			cout << "YES" << endl;
			a.clear();
			continue;
		}
		sort(a.begin(), a.end());
		int max1 = a[n - 1];
		int max2 = a[n - 2];
		if (max1 - max2 == 1 || max1 - max2 == 0) {
			cout << "YES" << endl;
		}
		else {
			cout << "NO" << endl;
		}
		a.clear();
		//cout << max1 << " " << max2 << endl;
		//cout << *a.rbegin() << endl;
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

轩Scott

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

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

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

打赏作者

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

抵扣说明:

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

余额充值