当前位置: 首页 > article >正文

蓝桥杯 1.语言基础

蓝桥杯 1.语言基础

文章目录

  • 蓝桥杯 1.语言基础
    • 编程基础
      • C++版本和基础格式
      • 输入输出
      • string的使用
      • 编程1-5
    • 竞赛常用库函数
      • sort()
      • 最值查找
      • 二分查找
      • 大小写转换
      • 全排列
      • 其他库函数
    • STL
      • pair
      • vector
      • list
      • stack
      • queue
      • set
      • map
      • 总结
      • 编程6-10

编程基础

C++版本和基础格式

版本:

  • 蓝桥杯使用C++11

基础格式

#include <bits/stdc++.h> // 万能头文件, VS中不支持使用
using namespace std;

int main(){
  cout << "Hello, World!" << endl; // 利用cout将字符串输出
  printf("Hello, World!"); // 利用printf将字符串输出
  return 0;
}

万能模板

#include <bits/stdc++.h> // 万能头文件, VS中不支持使用
using namespace std;
using ll = long long; // 开long long
const ll MAXN = 2e5 + 5; // 防止数组大小开太大或者太小
ll n, a[MAXN]; // 变量尽量使用全局

int main(){
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 关闭同步流, 提升cin和cout的速度, 如果使用scanf, printf, getchar一定要注释掉
  return 0;
}

输入输出

scanf和printf

  • 格式化输入输出
  • 效率高

cin和cout

  • 效率低

scanf和cin遇到空格和回车都会结束

取消同步流

// 由于cin和cout需要自动判断变量类型等内部原因, 读写效率比scanf和printf更低, 当数据量较大时, 可能导致程序运行超时. 我们可以通过取消同步流来加速cin和cout, 加速后效率相差无几
// 取消同步流
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

string的使用

string简介

  • 字符串管理: 自动处理字符串的内存分配和释放, 避免了手动管理内存的麻烦
  • 动态大小调整: string可以根据需要自动调整字符串的大小
  • 迭代器支持

string的声明和初始化

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

int main(){
	// 取消同步流 
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	string str1;
	string str2 = "Hello, World"; 
	string str3 = str2;
	string str4 = str2.substr(0, 5); // substr(起始位置, 长度) 
	const char* charArray = "Hello"; 
	string str5(charArray); // string(个数, 字符) 
	string str6(5, 'A');
	string str7;
//	cin >> str7; // cin遇到空格或者回车就会结束 
	getline(cin, str7); // 而getline()不会 
	
	cout << "str1: " << str1 << endl; // 空白
	cout << "str2: " << str2 << endl; // Hello, World
	cout << "str3: " << str3 << endl; // Hello, World 
	cout << "str4: " << str4 << endl; // Hello 
	cout << "str5: " << str5 << endl; // Hello 
	cout << "str6: " << str6 << endl; // AAAAA 
	cout << "str7: " << str7 << endl;
} 

各种基本操作

  • string转换成char[] (c_str())
#include <bits/stdc++.h> 
using namespace std;

int main(){
	// 取消同步流
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	char buf[100]; 
	scanf("%[^\n]", buf); // [^\n] 正则表达式, 排除空格和换行 
	string str(buf); 
	printf("%s", str.c_str()); // 在进行printf 输出时, 需要将string转换成c风格的字符串进行输出, 即string->char[] 
} 
  • 获取字符串长度(length/size)
// length
	string str = "Hello, World!";
	int length = str.length();	 
//	int length = str.size();
	cout << length << endl;
  • 拼接字符串(+或append)
// + append
	string str1 = "Hello"; 
	string str2 = "World!"; 
	string result1 = str1 + str2;
	string result2 = str1.append(", ").append(str2);
	cout << result1 << endl; 
	cout << result2 << endl;
  • 字符串查找(find)
// find: 查找成功则返回第一个出现的字符的位置或者子串的位置,查找失败则返回string::npos即为-1
	string str = "Hello, World!";
	size_t pos = str.find("World"); // 查找子字符串的位置
	if(pos != string::npos){
		cout << "Substring found at positions:" << pos << endl; 
	} else {
		cout << "Substring not found." << endl; 
	} 
  • 字符串替换(replace)
// replace
	string str = "Hello, World!";
	str.replace(7, 5, "Universe");  // (起始位置, 替换的长度, 替换字符串) 
	cout << str << endl;
  • 提取子字符串(substr)
// substr
	string str = "Hello, World!";
	string str3 = str.substr(7, 5); // substr(起始位置, 长度(不要越界)) 
	cout << str3 << endl; 
  • 字符串比较(compare)
// compare
	string str1 = "Hello"; 
	string str2 = "World!"; 
	int result = str1.compare(str2); // 比较字符串, 比较的方法是从小到大一个一个比较, 一旦遇到不相等的字符就确定大小关系 
	if(result == 0){
		cout << "Strings are equal." << endl; 
	} else if(result < 0){
		cout << "String 1 is less than String 2." << endl; 
	} else {
		cout << "String 1 is greater than String 2." << endl; 
	} 
  • 常用的遍历string的方法有两种
    • 循环枚举下标
    • auto枚举(其中&表示取引用, 如果对i修改将会改变原来的值)
	// 下标遍历 
	string s = "Hello";
	int i; 
	for(i = 0; i < s.length(); i++){
		cout << s[i]; 
	} 
	cout << endl; 
	
	// auto枚举 
	for(auto i : s){ // 这里的i是复制s中对应的字符串 
		cout << i;
		i = 'a'; 
	} 
	cout << endl;
	cout << s << endl; // 此时的s为"Hello" 
	
	for(auto &i : s){ // 这里的i就是s, 它们的地址相同 
		cout << i;
		i = 'a'; 
	} 
	cout << endl;
	cout << s << endl; // 此时的s为"aaaaa"
  • 逆序输出字符串

image-20250115083617550

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

int main(){
	// 取消同步流
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	// 手写的 
//	string str;
//	getline(cin, str); 
//	int i; 
//	for(i = 0; i < str.length() / 2; i++){
//		char tmp = str[i];
//		str[i] = str[str.length() - i - 1]; 
//		str[str.length() - i - 1] = tmp; 
//	} 
//	cout << str << endl;



	// 调用函数reverse(), begin(), end() 
//	string str;
//	getline(cin, str); 
//	reverse(str.begin(), str.end()); 
//	cout << str << endl; 


	// 调用函数swap() 
	string str;
	getline(cin, str); 
	int i; 
	for(i = 0; i < str.length() / 2; i++){
		swap(str[i], str[str.length() - i - 1]); 
	} 
	cout << str << endl; 
	return 0; 
} 

编程1-5

  • 编程1 妮妮的翻转游戏0

image-20250115090451493

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

int main(){
	// 取消同步流
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	int x;
	cin >> x;
	int result = 0; 
	if(x == 0){
		result = 1; 
	} else if(x == 1) {
		
	} else {
		cout << "输入错误" << endl; 
		return 0;
	}  
	cout << result << endl; 
	return 0; 
} 
  • 编程2 妮妮的蓝桥果园

image-20250115090540761

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

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	int n; // 原本的数量 
	int a; // 摘下的数量
	int b; // 挂上的数量
	cin >> n;
	cin >> a;
	cin >> b;
	int result = n - a + b; 
	cout <<  result << endl; 
	return 0;	
}
  • 编程3 蓝桥镇的月饼节

image-20250115090614537

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

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	int n, w; // 承重量,  每个月饼的重量
	cin >> n;
	cin >> w; 
	int result = n / w;
	cout << result << endl; 
	return 0;
}
  • 编程4 妮妮的蓝桥果园2

image-20250115090632955

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

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	int n; // 种类数
	int a[n]; // 每个水果的价值 
	cin >> n;
	int i; 
	int result = 0; 
	for(i = 0; i < n; i++){
		cin >> a[i];
	}
// 	for(i = 0; i < n; i++){
// 		result += a[i]; 
// 	}
// cout << result << endl; 

    cout << accumulate(a, a + n, 0) << '\n'; // 计算a到a+n之间的和, 初始值为0
	return 0; 
} 
  • 编程5 小蓝的决议

image-20250115090743544

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

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	int t; // 测试用例的数量 
	int n, x; // 成员总数, 赞成的成员数量
	cin >> t; 
	int i; 
	for(i = 0; i < t; i++){
// 		cin >> n;
// 		cin >> x;
// 		string result; 
// 		if((n % 2 == 0 && x >= n / 2) || (n % 2 != 0 && x > n / 2)){ 
// 			result = "YES"; 
// 		} else {
// 			result = "NO"; 
// 		} 
// 		cout << result << endl; 
// 	} 
	
	for(int i = 0; i < t; i++){
	    cin >> n >> x;
	    cout << (x >= (n + 2 - 1) / 2 ? "Yes" : "No") << "\n"; // a / b向上取整 等价于 (a+b-1)/b
	}
	return 0; 
}

竞赛常用库函数

sort()

简介

  • 需要引用头文件<algorithm>
  • 使用的是快速排序, 具有较好的平均时间复杂度, 一般为O(nlogn)

用法

  • sort(起始地址, 结束地址的下一位, *比较函数(*表示可写可不写))
#include <bits/stdc++.h>
using namespace std;

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	int arr[1000];
	int n;
	cin >> n; 
	int i;
	for(i = 0; i < n; i++){
		cin >> arr[i]; 
	} 
	
	sort(arr, arr + n); // 左闭右开, 默认升序 
	
	for(i = 0; i < n; i++){
		cout << arr[i] << " "; 
	} 
	return 0; 
} 
#include <bits/stdc++.h> 
using namespace std;

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	// 初始化v
	vector<int> v = {5, 1, 3, 9, 11}; 
	// 对数组进行排序
	sort(v.begin(), v.end());  // v[0], v[5]左闭右开
	int i; 
	for(i = 0; i < v.size(); i++){
		cout << v[i] << ' '; 
	} 
	return 0; 
} 

自定义比较函数

  • sort默认使用小于号进行排序(升序), 如果想要自定义比较规则, 可以传入第三个参数, 可以是函数或lambda表达式
#include <bits/stdc++.h> 
using namespace std;

bool cmp(int u, int v){ // 比较函数 
	return u > v; 
} 

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); 
	
	// 初始化v
	vector<int> v = {5, 1, 3, 9, 11}; 
	// 对数组进行排序
	sort(v.begin(), v.end(), cmp); // 传入函数名, 以降序的形式排序 
	int i; 
	for(i = 0; i < v.size(); i++){
		cout << v[i] << ' '; 
	} 
	return 0; 
} 
  • 升序降序

image-20250115170751570

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

bool cmp(int u, int v){
	return u > v;
} 

const int N = 5e5 + 3; 

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	int n;
	cin >> n;
	int a[N]; 
	int i;
	for(i = 0; i < n; i++){
		cin >> a[i]; 
	} 
	sort(a, a + n); 
	for(i = 0; i < n; i++){
		cout << a[i] << ' '; 
	} 
	cout << endl; 
	sort(a, a + n, cmp); 
	for(i = 0; i < n; i++){
		cout << a[i] << ' '; 
	}
	cout << endl;
	return 0; 
} 

最值查找

min和max函数

  • 可以传入两个值或者一个数组
  • 传入两个值的时候时间复杂度为O(1), 传入数组时时间复杂度为O(n), n为数组的大小
#include <bits/stdc++.h>
using namespace std;

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	cout << min(3, 5) << endl; // 3
	cout << min({1,2,3,4}) << endl; // 1
	cout << max(3, 5) << endl; // 5
	cout << max({1,2,3,4}) << endl; // 4
	
	return 0; 
} 

min_element和max_element

  • min_element(st, ed)返回地址[st, ed)中最小的那个值的地址(迭代器), 传入参数为两个地址或迭代器
  • 时间复杂度均为O(n), n为数组大小
#include <bits/stdc++.h>
using namespace std;

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	vector<int> v = {5, 1, 3, 9, 11}; // 初始化v
	
	// 输出最大的元素, *表示解引用, 即通过地址(迭代器)得到值
	cout << *max_element(v.begin(), v.end()) << endl; // 11
	
	return 0;
}

nth_element函数

  • nth_element(st, k, ed)进行部分排序, 返回值为void()
  • 其中第二个位置参数对应的元素处于排序后的正确位置, 其他位置元素的顺序可能是任意的, 但前面的都比它小, 后面的都比它大
  • 时间复杂度为O(n)
#include <bits/stdc++.h>
using namespace std;

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	vector<int> v = {5, 1, 7, 3, 10, 18, 9}; // 初始化v
	
	// 输出最大的元素, *表示解引用, 即通过地址(迭代器)得到值
	nth_element(v.begin(), v.begin() + 3, v.end());
	// 这里的v[3]将会位于排序后的位置, 其他的任意
	for(auto &i : v){
		cout << i << ' '; // 3 1 5 7 9 18 10 
	}
	
	return 0;
}
  • 求最大值, 最小值和平均数

image-20250116091535020

image-20250116091717417

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

const int N = 1e4 + 9;
int a[N];

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	int n;
	cin >> n;
	for(int i = 0; i < n; i++){
		cin >> a[i];
	}
	// 法一, 使用max_element 
//	cout << *max_element(a, a + n) << endl; // 传入起始地址和末尾地址 
//	cout << *min_element(a, a + n) << endl;

	// 法二, 使用max和min遍历 
	int mn, mx; 
	for(int i = 1; i < n; i++){
		mn = min(a[0], a[i]); 
		mx = max(a[0], a[i]); 
	} 
	cout << mx << endl; 
	cout << mn << endl;
	
	long long sum = 0;
	for(int i = 0; i < n; i++){
		sum += a[i]; // 求和 
	}
	// 先让sum变成浮点数再运算, 最后保留两位小数 
	cout << fixed << setprecision(2) << 1.0 * sum / n << endl; 
	
	return 0;
}

二分查找

二分法简介

  • 通过将问题的搜索范围一分为二, 迭代的缩小搜索范围, 知道找到目标或确定目标不存在
  • 适用于有序数据集合, 每次迭代可以将搜索范围缩小一半
  • 本质上也是枚举, 利用数据结构的单调性减少了很多不必要的枚举, 一般可以将O(n)的枚举优化到O(logn)
  • 常见的二分类型
    • 整数二分
    • 浮点二分
    • 二分答案(最常见)
  • 若以 r r r 作为答案, 那么答案区间在 [ l + 1 , r ] [l + 1, r] [l+1,r], 若以l作为答案, 那么答案区间在 [ l , r − 1 ] [l, r - 1] [l,r1]
  • 中点 m i d = ( l + r ) / 2 mid = (l + r) / 2 mid=(l+r)/2

整数二分

image-20250116102456719

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

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	int data[200]; 
	for(int i = 0; i < 200; i++){
		data[i] = 4 * i + 6; // 6 10 14 18 22 26 ... 
	} 
	int findNum;
	cin >> findNum; 
		
	
	
	int left = 0, right = 199;
	int mid; 
	while (left + 1 != right) { // 如果l和r相邻, 则说明l和r当中带等于号的是结果, 不相邻则继续循环
		mid = (left + right) / 2; 
		if (data[mid] >= findNum){ // 哪个地方有=就输出哪个
			right = mid;
		} else { // 这个地方没有=
			left = mid;  
		} 
	} 
	cout << right << endl; // right上面有=, 则输出right
	return 0;
}

浮点二分

  • 在某个实数范围内进行查找
  • 不常用

二分答案

  • 最常见最重要
  • 二分框架(时间复杂度O(logm)) + check函数(时间复杂度O(n))
  • 将答案进行二分, 然后再枚举出某个可能解后判断其是否可以更优或者是否合法

image-20250117092047443

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

const int N = 5e4 + 9; 
int a[N]; 
int L, n, m; // 起点到终点的距离, 起点和终点之间的岩石数量, 移走的岩石数量 

// 返回当最短距离为mid时需要移除的最少石头数量(贪心法) 
int check(int mid){
	int res = 0, lst = 0;
	for(int i = 1; i <= n; i++){
		// 将i移除 
		if(a[i] - a[lst] < mid){
			res++; 
		} else {
			lst = i; 
		} 
	} 
	// 将lst移除 
	if(L - a[lst] < mid){
		res++; 
	}
	return res; 
} 

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	
	cin >> L >> n >> m; 
	for(int i = 1; i <= n; i++){
		cin >> a[i]; // 第i块岩石与起点的距离 
	} 
	int l = 0, r = 1e9 + 5; 
	while(l + 1 != r){
		int mid = (l + r) / 2;
		if(check(mid) <= m){
			l = mid; 
		} else {
			r = mid; 
		} 
	} 
	cout << l << '\n'; 
	return 0;
}

image-20250117101300445

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


long long n, m, k; // n*m矩阵, 第k大的元素
long long rnk(long long mid){
	long long res = 0;
	for(int i = 1; i <= n; i++){
		res += min(m, mid / i); 
	} 
	return res; 
} 

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

	cin >> n >> m >> k;
	long long l = 0, r = 1e14;
	while(l + 1 != r){
		long long mid = (l + r) / 2; 
		if(rnk(mid) >= k){
			r = mid; 
		} else {
			l = mid;	
		} 
	} 
	cout << r << '\n'; 
	return 0;
}

大小写转换

islower和isupper函数

  • 检查一个字符是否是小写或大写
  • 包含头文件<cctype>
  • 函数返回值为bool类型
#include <bits/stdc++.h>
using namespace std; 

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

	char ch1 = 'A'; 
	char ch2 = 'b'; 
	
	if(islower(ch1)){
		cout << ch1 << " is a lowercase letter." << endl; 
	} else {
		cout << ch1 << " is not a lowercase letter." << endl;
	} 

	if(isupper(ch2)){
		cout << ch2 << " is an uppercase letter." << endl; 
	} else {
		cout << ch2 << " is not an uppercase letter." << endl;
	} 

	return 0;
}

tolower和toupper函数

  • tolower(char ch)将ch转换为小写字母, 如果ch不是大写字母则不进行操作, toupper同理
#include <bits/stdc++.h>
using namespace std; 

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

	char ch1 = 'A'; 
	char ch2 = 'b'; 
	
	char lowercaseCh1 = tolower(ch1); 
	cout << "Lowercase of " << ch1 << " is " << lowercaseCh1 << endl; 
	
	char uppercaseCh2 = toupper(ch2); 
	cout << "Uppercase of " << ch2 << " is " << uppercaseCh2 << endl;

	return 0;
}

ascii码

  • ‘A’(65), ‘Z’(90)
  • ‘a’(97), ‘z’(122)
#include <bits/stdc++.h>
using namespace std; 

char convertedCh(char ch){
	if(islower(ch)){
		ch = toupper(ch); 
	} else if(isupper(ch)){
		ch = tolower(ch); 
	} 
	return ch; 
} 

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

//	char ch = 'a'; 
//	char convertedCh;
//	
//	if(ch >= 'A' && ch <= 'Z'){
//		convertedCh = ch - 'A' + 'a';
//		cout << convertedCh << endl; 
//	} else {
//		convertedCh = ch - 'a' + 'A';
//		cout << convertedCh << endl; 
//	}

	string s;
	getline(cin, s); 
	
//	for(auto &i : s){
//		i = convertedCh(i);	
//	}
	for(int i = 0; i < s.length(); i++){
		s[i] = convertedCh(s[i]);
	} 
 
	cout << s << endl; 
	return 0;
}

全排列

next_permutation()函数

  • permutation(排列)
  • 用于生成当前序列的下一个排列. 按照字典序对序列进行重新排列, 如果存在下一个排列, 则将当前序列更改为下一个排列, 并返回true, 如果当前序列已经是最后一个排列, 则将序列更改为第一个排列, 并返回false
  • 例如
    • 123, 132, 213, 231, 312, 321
    • abc, acb, bac, bca, cab, cba
#include <bits/stdc++.h>
using namespace std;

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	vector<int> nums = {1, 2, 3};
    
    // 初始排列
	for(int num : nums){
		cout << num << " "; 
	} 
	cout << endl;
	
	// 生成下一个排列
	while(next_permutation(nums.begin(), nums.end())){ // 
		for(int num : nums){
			cout << num << " "; 
		} 
		cout << endl;	 
	} 
	
	return 0; 
} 

prev_permutation()函数

  • 与next_permutation()函数相反

  • 用于生成当前序列的上一个排列. 按照字典序对序列进行重新排列, 如果存在上一个排列, 则将当前序列更改为上一个排列, 并返回true, 如果当前序列已经是第一个排列, 则将序列更改为最后一个排列, 并返回false

  • 例如

    • 321, 312, 231, 213, 132, 123
// 以数组的形式
int a[10];

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
    // 初始化
	int j = 0;
	for(int i = 4; i >= 1; i--){
	    a[j] = i;
	    j++;
	}
	bool tag = true;
	while(tag){
	    for(int i = 0; i < 4; i++){
            cout << a[i] << ' ';
        }     
    	cout << endl;
    	tag = prev_permutation(a, a + 4);
	}
	
	return 0; 
}

其他库函数

memset()

  • 用于设置内存块值(初始化数组)

  • 头文件<cstring>

  • 函数原型void* memset(void* ptr, int value, size_t num);

    • ptr: 指向要设置值的内存块的指针
    • value: 要设置的值(通常是一个整数, 8bit位(1byte)二进制数)
    • num: 要设置的字节数
例如:
// 将数组arr中的所有元素全部设置为0
int arr[10];
memset(arr, 0, sizeof(arr));
  • 注意: 该函数对于非字符类型(非char类型)的数组可能会产生为定义行为, 因为char类型是8bit(1byte), 而比如说int类型, 是32bit(4byte), 它会将该数字分为4部分, 对每一部分的最后一位二进制取value, 所以此时形成的数字会不固定.

swap()

  • swap(&a, &b)
  • 接收两个参数, 可以交换任意类型的变量, 包括基本数据类型和自定义类型
int a = 10;
int b = 20;
swap(a, b);

reverse()

  • 用于反转容器中元素顺序
  • 头文件**<algorithm>**
  • 函数原型template<class BidirIt> void reverse(BidirIt first, BidirIt last)
  • 接收两个参数
    • first: 指向容器中要反转的第一个元素的迭代器
    • last: 最后一个元素的下一个位置(左闭右开)的迭代器
  • 可以用于反转各种类型的容器, 包括数组, 向量, 链表
  • 只能用于支持双向迭代器的容器, 因为它需要能够向前和向后遍历容器中的元素
#include <bits/stdc++.h>
using namespace std;

int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	vector<int> v = {1, 2, 3, 4, 5};
	reverse(v.begin(), v.end());
	
	for(int num : v){
	    cout << num << ' '; // 5 4 3 2 1
	}
	cout << endl;
	
	return 0; 
}

unique()

  • 用于去除容器中相邻重复元素

    • 如果需要去除所有重复元素, 可以先对容器进行排序, 然后再使用unique()
  • 头文件<algorithm>

  • 函数原型template<class ForwardIt> ForwardIt unique(ForwardIt first, ForwardIt last)

  • 接收两个参数

    • first: 指向容器中要反转的第一个元素的迭代器
    • last: 最后一个元素的下一个位置(左闭右开)的迭代器
  • 返回一个指向去重后范围的尾后迭代器

  • 时间复杂度O(n), 但是一般去重之前都需要进行排序O(nlogn), 所以一般都是以排序的时间复杂度作为依据

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    vector<int> v = {1, 1, 2, 2, 3, 3, 3, 4, 4, 5};
    auto it = unique(v.begin(), v.end()); // 此时的it指向的是尾后迭代器, 也就是v中的第二个3
    for(int num : v){
        cout << num << " "; // 1 2 3 4 5 3 3 4 4 5 
    }
    cout << endl;
    
    v.erase(it, v.end()); // 将v中的[it, end)范围内的元素删除
    for(int num : v){
        cout << num << " "; // 1 2 3 4 5 
    }
    cout << endl;
    
    return 0;
}
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    int a[] = {3, 1, 2, 2, 3};
    sort(a, a + 5); // 对于重复但不相邻的数组, 就需要先进行排序, 然后去重
    int n = unique(a, a + 5) - a; // unique()返回一个指向去重后尾后的迭代器it, it - a返回给n(这是两个地址进行运算, 为了将后面多余的元素忽略)
    for(int i = 0; i < n; i++){
        cout << a[i] << ' ';
    }
    
    return 0;
}

STL

pair

定义和结构

  • 是一个模板类, 用于表示一对值的组合
  • 头文件<utility>
  • 有两个模板参数T1和T2, 分别表示第一个值和第二个值的类型
template<class T1, class T2> // 两个模板参数, 分别表示第一个和第二个值的类型
struct pair{
    T1 first;
    T2 second; // 成员变量, 分别表示第一个和第二个值
    
    // 构造函数
    pair();
    pair(const T1& x, const T2& y);
    
    // 比较运算符重载
    bool operator==(const pair& rhs) const;
    bool operator!=(const pair& rhs) const;
    
    // 其他成员函数和特性
};
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    pair<int, double> p1(1, 3.14);
    pair<char, string> p2('a', "hello");
    
    cout << p1.first << ", " << p1.second << endl; // 1, 3.14
    cout << p2.first << ", " << p2.second << endl; // a, hello
    
    return 0;
}

嵌套

  • 可以将一个pair对象作为另一个pair对象的成员
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    pair<int, int> p1(1, 2);
    pair<int, pair<int, int>> p2(3, make_pair(4, 5));
    pair<pair<int, int>, pair<int, int>> p3(make_pair(6, 7), make_pair(8, 9));
    
    cout << p1.first << ", " << p1.second << endl;
    cout << p2.first << ", " << p2.second.first << ", " << p2.second.second << endl;
    cout << p3.first.first << ", " << p3.first.second << ", " << p3.second.first << ", " << p3.second.second << endl;
    return 0;
}

自带排序规则

  • 按照first成员进行升序排序, 如果first成员相等, 则按照second成员进行升序排序
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    vector<pair<int, int>> vec;
    vec.push_back(make_pair(3, 2));
    vec.push_back(make_pair(1, 4));
    vec.push_back(make_pair(2, 1));
    
    sort(vec.begin(), vec.end());
    
    for(const auto& p : vec){
        cout << p.first << ", " << p.second << endl;
    }

	/*
        1, 4
        2, 1
        3, 2
	*/
	return 0;
}

代码示例

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

// 人结构体
struct Person{
    string name;
    int age;
};

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    // 创建一个存储Person对象的向量
    vector<Person> people;
    
    // 添加一些Person对象到向量中
    people.push_back({"Alice", 25});
    people.push_back({"Bob", 30});
    people.push_back({"Charlie", 20});
    
    // 创建一个存储pair的向量, 每个pair包含一个Person对象和一个评分
    vector<pair<Person, int>> scores;
    
    // 添加一些pair到向量中
    scores.push_back({people[0], 90});
    scores.push_back({people[1], 85});
    scores.push_back({people[2], 95});
    
    // 姓名, 年龄, 评分
    for(const auto& pair : scores){
        cout << "Name: " << pair.first.name << endl;
        cout << "Age: " << pair.first.age << endl;
        cout << "Score: " << pair.second << endl;
        cout << endl;
    }
    
    return 0;
}

vector

定义和特性

  • vector是一个动态数组容器, 它会根据元素的数量动态调整大小, 可以存储一系列相同数据类型的元素
  • 头文件<vector>
  • 语法vector<T类型> vec;
  • 元素访问: []
  • 元素添加
    • push_back()在末尾添加元素
    • insert()在指定位置
  • 元素删除
    • pop_back()在末尾删除元素
    • erase()在指定位置
  • 大小管理
    • size()获取容器大小
    • empty()检查容器是否为空
    • resize()调整容器大小, 一般在程序的开头
    • clear()清空容器
  • 迭代器
    • begin()获取指向第一个元素的迭代器
    • end()最后一个

常用函数

  • push_back()
  • pop_back(), 一定要保证vector非空
  • begin()
  • end()

排序去重

  • sort()
  • unique()配合erase()

代码示例

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    vector<int> nums;
    // 在末尾添加元素
    nums.push_back(1);
    nums.push_back(6);
    nums.push_back(8);
    nums.push_back(2);
    nums.push_back(6);
    nums.push_back(1);
    
    for(int num : nums){
        cout << num << " "; // 1 6 8 2 6 1 
    }
    cout << endl;
    
    // 排序
    sort(nums.begin(), nums.end());
    for(int num : nums){
        cout << num << " "; // 1 1 2 6 6 8 
    }
    cout << endl;
    
    // 去重
    nums.erase(unique(nums.begin(), nums.end()), nums.end());
    for(int num : nums){
        cout << num << " "; // 1 2 6 8 
    }
    cout << endl;
    
    // 在指定位置插入元素
    nums.insert(nums.begin() + 2, 3); // 在nums.begin() + 2位置插入元素3
    for(int num : nums){
        cout << num << " "; // 1 2 3 6 8 
    }
    cout << endl;
    
    // 删除指定位置的元素
    nums.erase(nums.begin() + 4);
    for(int num : nums){
        cout << num << " "; // 1 2 3 6 
    }
    cout << endl;
    
    // 检查是否为空
    if(nums.empty()){
        cout << "为空" << endl;
    } else {
        cout << "非空" << endl; // 非空
    }
    
    // 获取大小
    cout << nums.size() << endl; // 4
    
    // 清空
    nums.clear();
    
    if(nums.empty()){
        cout << "为空" << endl; // 为空
    } else {
        cout << "非空" << endl;
    }
    
    
    return 0;
}

list

定义和结构

  • 使用频率不高, 在做题时几乎遇不到
  • 是一种双向链表容器, 以节点的形式存储元素, 并使用指针将这些节点链接在一起, 形成一个链表结构(不能随机访问list容器中的对象, 可以从两端顺序访问元素)
  • 双向性: 每个节点都包含指向前一个和后一个节点的指针
  • 动态大小: 因为是容器
  • 不连续存储: 链表中的节点可以在内存中任意位置分布, 不要求连续存储, 因此插入和删除操作不会导致元素的移动
  • 提供了一系列成员函数和迭代器来操作和访问链表中的元素
  • 注意: list是双向链表, 因此插入和删除操作的时间复杂度是O(1), 但访问和查找操作的时间复杂度是O(n), 因此需要频繁进行随机访问操作, 可能更适合使用支持随机访问的容器, 例如vector或deque(双端队列)
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    list<int> myList;
    
    // 在链表尾部插入元素
    myList.push_back(1);
    myList.push_back(4);
    myList.push_back(3);
    myList.push_back(6);
    
    // 在链表头部插入元素
    myList.push_front(9);
    
    for(int num : myList){ // int也可以写成auto
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}

常用函数

  • push_back()在末尾插入
  • push_front()在开头插入
  • pop_back()删除末尾
  • pop_front()删除开头
  • size()
  • empty()
  • clear()
  • front()返回链表中第一个元素的引用
  • back()最后一个
  • begin()
  • end()
  • insert()
  • erase()

代码示例

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    list<int> myList;
    // 插入元素
    for(int i = 1; i <= 5; i++){
        myList.push_back(i);
    }
    // 输出
    for(auto num : myList){
        cout << num << ' '; // 1 2 3 4 5
    }
    cout << endl;
    
    // 反转
    reverse(myList.begin(), myList.end());
    for(auto num : myList){
        cout << num << ' '; // 5 4 3 2 1
    }
    cout << endl;
    
    // 插入
    myList.insert(++myList.begin(), 0);
    for(auto num : myList){
        cout << num << ' '; // 5 0 4 3 2 1
    }
    cout << endl;
    
    // 删除
    myList.erase(++ ++ myList.begin(), -- myList.end());
    for(auto num : myList){
        cout << num << ' '; // 5 0 1
    }
    cout << endl;
    
    // 大小
    cout << myList.size() << endl; // 3
    
    return 0;
}

stack

定义和结构

  • 是一种后进先出LIFO(Last In First Out)的数据结构
  • 头文件<stack>
  • 时间复杂度O(1)
  • 不能遍历
  • 如果将一个数组的元素依次放入栈, 再依次取出, 则可以将数组翻转

常用函数

  • push(x)在栈顶插入元素x
  • pop()弹出栈顶元素
  • top()返回栈顶元素
  • empty()
  • size()

代码示例

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    stack<int> myStack;
    
    // 插入元素
    myStack.push(4);
    myStack.push(2);
    myStack.push(6);
    myStack.push(1);
    myStack.push(7);
    
    // 获取栈顶元素
    cout << myStack.top() << endl; // 7
    
    // 弹出栈顶元素
    myStack.pop();
    cout << myStack.top() << endl; // 1
    
    // 检查是否为空
    if(myStack.empty()){
        cout << "为空" << endl;
    } else {
        cout << "非空" << endl; // 非空
    }
    
    // 获取大小
    cout << myStack.size() << endl; // 4
    
    return 0;
}

queue

queue队列

  • 先进先出(FIFO)
  • 时间复杂度O(1)
  • push(x)在队尾插入元素x
  • pop()弹出队首元素
  • front()返回队首元素
  • back()返回队尾元素
  • empty()
  • size()

priority_queue优先队列

  • 按照一定的优先级进行排序, 默认情况下, 按照降序进行排序, 即最大元素位于队列的前面
  • 如果队列中的元素类型比较简单, 可以直接使用**greater<T>**来修改比较方法
函数描述时间复杂度
push()在优先队列插入元素xO(logn)
pop()弹出优先队列的顶部元素O(logn)
top()返回优先队列的顶部元素O(1)
empty()O(1)
size()O(1)
#include <bits/stdc++.h>
using namespace std;

struct Compare{
    bool operator()(int a, int b){
        return a > b;
    }
};

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    priority_queue<int, vector<int>, Compare> pq;
        
    return 0;
}

deque双端队列

  • 允许在两端进行高效插入和删除操作, 其他的和queue一样

  • push_back(x)

  • push_front(x)

  • pop_back()

  • pop_front()

  • front()

  • back()

  • empty()

  • size()

  • clear()

例题讲解

image-20250118211750780

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    int m; cin >> m;
    queue<string> V, N;
    while(m--){
        string op; cin >> op;
        if(op == "IN"){
            string name, q; cin >> name >> q;
            if(q == "V"){
                V.push(name); // 添加`
            } else {
                N.push(name);
            }
        } else if(op == "OUT"){
            string q; cin >> q;
            if(q == "V"){
                V.pop(); // 删除
            } else {
                N.pop();
            }
        }
    }
    while(V.size()){ // 队列不能遍历, 应该将队首的元素依次输出弹出并再次输出下一个队首元素
        cout << V.front() << endl;
        V.pop();
    }
    while(N.size()){
        cout << N.front() << endl;
        N.pop();
    }

    
    return 0;
}

image-20250119093421088

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    int n; cin >> n;
    priority_queue<ll, vector<ll>, greater<ll>> pq; // 修改比较函数, 默认为降序, 使用greater修改为升序, 同时要使用vector容器
    // 输入
    for(int i = 0; i < n; i++){
        ll num; cin >> num;
        pq.push(num);
    }
    // 结果
    ll result = 0;
    while(pq.size() >= 2){ // 保证队列元素大于等于2
        ll x = pq.top();
        pq.pop(); // 取出顶部元素再弹出
        
        ll y = pq.top();
        pq.pop(); // 取出顶部元素再弹出
        
        result += x + y; // 将队列前两个元素相加并加到结果中
        pq.push(x + y); // 最后放回队列中以便下一次使用
    }
    cout << result << endl;
    return 0;
}

set

set集合

  • 用于存储一组唯一的元素(不允许重复的元素存在, 当插入一个重复元素时, set会自动忽略该元素), 并按照一定的排序规则进行排序, 默认为升序

  • 内部实现使用了红黑树(一种自平衡的二叉搜索数)来存储元素, 并保持元素的有序性, 这使得在set中插入, 删除和查找元素的时间复杂度都是对数时间, 即O(logn)

函数描述时间复杂度
insert()插入O(logn)
erase()删除O(logn)
find()查找O(logn)
lower_bound()返回第一个不小于给定值的迭代器O(logn)
upper_bound()返回第一个大于给定值的迭代器O(logn)
size数量O(1)
empty检查是否为空O(1)
clear清空O(n)
begin()起始位置O(1)
end()末尾O(1)
rbegin()返回指向集合末尾位置的逆向迭代器O(1)
rend()返回指向集合起始位置的逆向迭代器O(1)
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    set<int, greater<int>> mySet; // 修改set比较函数
    
    mySet.insert(5);
    mySet.insert(2);
    mySet.insert(7);
    mySet.insert(1);
    mySet.insert(9);
    
    for(auto num : mySet){
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}

multiset多重集合

  • 和set一样, 不同的是, multiset容易允许存储重复的元素

  • 函数也和set一样

unordered_set无序集合

  • 作为了解即可
  • 用于存储一组唯一的元素, 并且没有特定的顺序

代码示例

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    set<int> mySet;
    // 插入元素
    mySet.insert(5);
    mySet.insert(2);
    mySet.insert(8);
    mySet.insert(2); // 重复元素
    mySet.insert(1);
    
    // 遍历集合
    for(auto num : mySet){
        cout << num << " ";
    }
    cout << endl;
    
    // 查找元素
    int searchValue = 5;
    auto it = mySet.find(searchValue);
    if(it != mySet.end()){
        cout << searchValue << " found in the set." << endl;
    } else {
        cout << searchValue << " not found in the set." << endl;
    }
    
    // 移除元素
    int removeValue = 2;
    mySet.erase(removeValue);
    for(auto num : mySet){
        cout << num << " ";
    }
    cout << endl;
    
    // 清空
    mySet.clear();
    if(mySet.empty()){
        cout << "Set is empty." << endl;
    } else {
        cout << "Set is not empty." << endl;
    }
    
    
    return 0;
}
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    multiset<int> myMultiset;
    // 插入元素
    myMultiset.insert(5);
    myMultiset.insert(2);
    myMultiset.insert(8);
    myMultiset.insert(2); // 允许重复元素
    myMultiset.insert(1);
    
    // 遍历集合
    for(auto num : myMultiset){
        cout << num << " ";
    }
    cout << endl;
    
    // 移除元素
    int removeValue = 2;
    myMultiset.erase(removeValue); // 将重复元素全部移除
    // myMultiset.erase(myMultiset.find(removeValue)); // 移除一个
    for(auto num : myMultiset){
        cout << num << " ";
    }
    cout << endl;
    
    
    return 0;
}

map

map

  • 是一种关联容器, 用于存储一组键值对(key-value pairs), 其中每个键(key)都是唯一的
  • 根据来自动进行排序, 并可以通过键快速查找对应的值
  • 使用**红黑树(Red-Black Tree)**数据结构来实现, 具有较快的插入, 删除和查找时间复杂度, O(logn)
函数描述时间复杂度
insert()插入O(logn)
erase()删除O(logn)
find()查找O(logn)
lower_bound()返回第一个不小于指定键的迭代器O(logn)
upper_bound()返回第一个大于指定键的迭代器O(logn)
count(key)统计key的个数O(logn)
size整个的数量O(1)
empty检查是否为空O(1)
clear清空O(n)
begin()起始位置O(1)
end()末尾O(1)

multimap

  • 几乎不用
  • 类似于map, 但允许存储多个具有相同键的键值对
  • erase删除元素时和mutiset类似

unordered_map

  • 一般不用
  • 类似于map, 但是它是使用哈希函数将键映射到存储桶中

代码示例

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    map<int, string> myMap = {
        {1, "Apple"},
        {2, "Banana"},
        {3, "Orange"}
    };
    
    // 插入元素
    myMap.insert({4, "Grapes"});
    
    // 查找和访问元素
    cout << myMap[2] << endl;
    
    // 打印
    for(auto num : myMap){
        cout << "key: " << num.first << ", value: " << num.second << ' ';
    }
    cout << endl;
    
    // 删除元素
    myMap.erase(3);
    
    // 判断元素是否存在
    if(myMap.count(3) == 0){
        cout << "key 3 not found." << endl;
    }
    
    // 清空
    myMap.clear();
    
    // 判断是否为空
    if(myMap.empty()){
        cout << "Map is empty." << endl;
    }
    
    return 0;
}

总结

3226宝藏排序II

image-20250119164855429

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    ll n; cin >> n;
    vector<ll> vec;
    // 输入
    for(int i = 0; i < n; i++){
        int x; cin >> x;
        vec.push_back(x);
    }
    // 排序
    sort(vec.begin(), vec.end());
    // 输出
    for(auto num : vec){
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}

1624小蓝吃糖果

image-20250119164920556

// 自己写的

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    int n; cin >> n;
    priority_queue<int> pq;
    
    // 输入
    for(int i = 0; i < n; i++){
        int x; cin >> x;
        pq.push(x);
    }
    
    while(pq.size() >= 2){
        int x = pq.top(); pq.pop();
        int y = pq.top(); pq.pop();
        
        while(x != 0 && y != 0){
            x--;
            y--;
        }
        pq.push(x + y);
    }
    // 输出
    if(pq.top() == 1){
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
    
    return 0;
}

image-20250120085552199

// 解析

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    ll n; cin >> n;
    ll sum = 0, mx = 0;
    for(int i = 0; i < n; i++){
        ll x; cin >> x;
        mx = max(mx, x);
        sum += x;
    }
    // 不连续吃到两种同样的糖果 等价于 sum - mx >= mx - 1
    if(sum - mx >= mx - 1){ // sum - mx: 其他的数量
                            // mx - 1: mx-1个空隙
                            // 其他的数量要大于等于空隙数量(也就是这些数的和必须得足够插入到空隙里面)
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
    
    return 0;
}

2490小蓝的括号串1

image-20250119164949292

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    int n; cin >> n;
    string str; cin >> str;
    stack<int> stk;
    bool flag = true;
    for(int i = 0; i < n; i++){
        if(str[i] == '('){ // 是'('则压栈
            stk.push('(');
        } else {
            if(stk.size() && stk.top() == '('){ // 长度不为0并且栈顶为'('则弹栈(说明此时栈顶的元素是'('且匹配到的是')')
                stk.pop();
            } else{
                flag = false; // 此时说明长度不为0或者栈顶不是'(', 则')'无法匹配, 所以flag改为false
            }
        }
    }
    if(stk.size()){ // 栈中还有元素, 说明还有括号未配对, 则要将flag改为false
        flag = false;
    }
    cout << (flag ? "Yes" : "No") << endl;
    
    return 0;
}

1531快递分拣

image-20250119165022624

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    int n; cin >> n;
    map<string, vector<string>> m;
    vector<string> citys;
    // 输入
    for(int i = 0; i < n; i++){
        string s, p; cin >> s >> p;
        if(!m.count(p)){
            citys.push_back(p);
        }
        m[p].push_back(s);
    }
    
    // 输出
    for(auto city : citys){
        cout << city << m[city].size() << endl;
        for(auto i : m[city]){
            cout << i << endl;
        }
    }
    
    return 0;
}
	/*
        10
        1234 北京
        5432 上海
        asdf 天津
        5674 北京
        12345 上海
        234sda 济南
        346asd 成都
        345678765 武汉
        123425677 沈阳
        123qwesd 成都
    */

编程6-10

image-20250120100434303

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

ll n, x;

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    map<ll, ll> cnt;
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> x;
        cnt[x]++;
    }
    ll ans = 0;
    for(auto it : cnt){
        if(it.second >= it.first){
            ans += it.second - it.first;
        } else {
            ans += it.second;
        }
    }
    cout << ans << "\n";
    return 0;
}

image-20250120105131922

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MAXN = 2e3 + 5;
bitset<MAXN> b[MAXN];

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    ll n; cin >> n;
    ll ans;
    string s;
    for(int i = 1; i <= n; i++){
        cin >> s;    
        s = " " + s;
        for(int j = i + 1; j <= n; j++){
            b[i][j] = s[j] - '0';
        }
    }
/*
4
0011
0011
1101
1110

*/
    for(int i = 1; i <= n; i++){
        for(int j = i + 1; j <= n; j++){
            if(b[i][j]){
                ans += (b[i] & b[j]).count();
            }
        }
    }
    cout << ans << "\n";
    
    
    
    return 0;
}

image-20250120110157429

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

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    ll n; cin >> n;
    map<string, ll> mp;
    for(int i = 0; i < n; i++){
        string str; cin >> str;
        
        if(str == "find"){
            string author; cin >> author;
            cout << mp[author] << "\n";
            
        } else if(str == "add"){
            string bookname, author; 
            cin >> bookname >> author;
            mp[author]++;
        }
    }
    /*
        7
        find author1
        add book1 author1
        find author1
        add book1 author1
        find author1
        add book1 author2
        find author2    
    */
    return 0;
}

image-20250120114005851

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

using ll = long long;
const ll MAXN = 2e5 + 5;
ll a[MAXN];
map<ll, ll> mp;
ll calc(ll x){
    return mp[x] + mp[x - 1] + mp[x + 1];
}

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    int n; cin >> n;
    for(int i = 0; i < n; i++){
        cin >> a[i];
        mp[a[i]]++;
    }
    
    /*
        1: 0 1 2
        2: 1 2 3
        3: 2 3 4
    */
    
    ll ans = 0;
    for(int i = 0; i < n; i++){
        ans = max(ans, calc(a[i]));
        ans = max(ans, calc(a[i] + 1));
        ans = max(ans, calc(a[i] - 1));
    }
    cout << ans << "\n";
    
    return 0;
}

image-20250120114937918

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MAXN = 2e5 + 5;


int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    
    ll n, q; cin >> n >> q;
    string s; cin >> s; // 010011
    s = " " + s;
    set<ll> st;

    for(int i = 0; i < n; i++){
        if(s[i] == '1'){
            st.insert(i);
        }
    }
    while(q--){
        ll ch, x;
        cin >> ch;
        if(ch == 1){
            if(!st.size()){
                cout << -1 << "\n";
            } else {
                cout << (*st.begin()) << "\n";
            }
        } else {
            cin >> x;
            if(s[x] == '1'){
                st.erase(x);
                s[x] = '0';
            } else {
                st.insert(x);
                s[x] = '1';
            }
        }
    }   
    /*
        6 5
        010011
        1
        2 2
        1
        2 6
        1
     */
    
    return 0;
}

http://www.kler.cn/a/557766.html

相关文章:

  • 深蓝学院自主泊车第3次作业-IPM
  • SQL面试题集:识别互相关注的用户
  • 八股文实战之JUC:静态方法的锁和普通方法的锁
  • go json处理 encoding/json 查询和修改gjson/sjson
  • java开发工程师面试技巧
  • 对计算机中缓存的理解和使用Redis作为缓存
  • LeetCode 2506.统计相似字符串对的数目:哈希表+位运算
  • Trae+Qt+MSVC环境配置
  • 运筹说 第132期 | 矩阵对策的基本理论
  • PostgreSQL:更新字段慢
  • 索引与Redis 知识点
  • 易飞ERP查询报表提示:报表档的字段数为21但要写到报表档的字段数为42;报表没有信息;;
  • 策略模式介绍和代码示例
  • 对Revit事务机制的一些推测
  • Webpack的基本功能有哪些
  • 负载均衡集群( LVS 相关原理与集群构建 )
  • RT-Thread+STM32L475VET6——icm20608传感器
  • 可变参数学习
  • 论文略:ACloser Look into Mixture-of-Experts in Large Language Models
  • 详解单例模式、模板方法及项目和源码应用