2024暑期集训第2周——“圈圈圆圆圈圈,天天蒙圈的我~~”

一、学习到的知识点

1、栈

概念:

栈是一种线性数据结构。栈只允许在一端(称为栈顶)进行插入和删除操作。栈中没有元素时,称为空栈。栈的插入操作通常被称为“压栈”(push),而删除操作则被称为“弹栈”(pop)。

语法:

stack<int> a;
a.push(e);   //将e放入栈顶
a.pop();     //将栈顶元素出栈
a.top();    //获取栈顶元素
a.size();    //获取栈中有效元素个数
a.empty();   //检测栈是否为空

2、队列

概念:

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出的线性表。允许插入的一端称为队尾,允许删除的一端称为队头。

语法:

queue<int> a;
a.push(a);   //将元素插入队列的末尾
a.front();   //返回队列的第一个元素
a.back();    //返回队列的最后一个元素
a.pop();     //从队列的开头删除元素
a.size();    //返回队列中元素的数量
a.empty();   //检查队列是否为空,如果为空则返回true,否则返回false

3、优先队列

概念:

既然是队列那么先要包含头文件#include <queue>。而他和queue不同的地方就在于我们可以自定义其中数据的优先级,让优先级高的排在队列前面优先出队。

优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。

语法:

priority_queue<int, vector<int>,greater<int> > q;
                                    ↑
                       从小到大排序,不写的话则为从大到小排序

4、函数stio( ) (自学)

在C++中,stoi()函数是将字符串转换为整数的函数,其作用是将一个字符串类型的数字转换为一个整数类型的数字。

stoi()函数的原型如下:

int stoi(const string& str, size_t* pos = 0, int base = 10);

其中,str是要转换的字符串,pos是一个指向size_t类型的指针,用于存储转换过程中第一个无法转换的字符的位置,base表示要转换的进制数,默认为10进制。

stoi()函数会从字符串的开头开始读取数字字符,直到遇到第一个非数字字符为止,然后将读取到的数字字符转换为整数类型的数字。如果字符串的开头不是数字字符,则返回0。

例如,stoi("123")的返回值为整数类型的123。

5、函数substr( )   (自学)

ubstr()是C++标准库中的一个成员函数,可用于从一个字符串中提取子串。它的语法如下:

std::string substr (size_t pos, size_t len) const;

其中pos是子字符串的起始位置(从0开始计数),len是子字符串的长度。

以下是一个简单的例子,展示如何使用substr函数取出字符串中间的几个字符:

#include <iostream>
#include <string>
 
int main() {
    std::string str = "Hello, World!";
    // 取出从位置6开始的5个字符
    std::string sub = str.substr(6, 5);
    std::cout << sub << std::endl; // 输出: World
    return 0;
}

在这个例子中,程序将输出字符串"Hello, World!"中第6个字符开始的连续5个字符"World"。如果len超出了字符串的长度,它将返回从pos到字符串末尾的一个子字符串。

6、集合set

概念:

set是一个集合,所有元素在插入时,会自动排序,并且不能插入重复元素。底层代码为红黑树。

set不允许容器中有重复的元素。

语法:

set<Type> a;
a.insert(val);  //将值为val的元素插入set容器中
a.erase(val);   //从set容器中删除值等于val的元素
a.size();	    //返回set容器中元素的个数
a.empty();      //检查set容器是否为空,如果为空则返回true,否则返回false
a.clear();      //删除set容器中的所有元素
a.count(val);   //返回set容器中值等于val的元素的个数(返回值只能是0或1,因为set中元素唯一)
	

 进阶篇:(迭代器)

a.begin();             //返回set第一个元素的地址的迭代器
a.end();               //返回set最后一个元素的地址的下一个地址的迭代器
a.find(val);	       //返回一个迭代器,指向set容器中值等于val的元素,如果未找到则返回指向容器末 
                       //尾的迭代器end()。
a.erase(start, end);   //删除迭代器范围内的元素。
a.lower_bound(val);	   //返回一个迭代器,指向set容器中第一个不小于val的元素
a.upper_bound(val);	   //返回一个迭代器,指向set容器中第一个大于val的元素
a.equal_range(val);    //返回一个pair,包含两个迭代器,分别指向set容器中等于val的元素的起始位置和    
                       //结束位置

7、map

概念:

map简介

map是STL的一个关联容器,它提供一对一的hash

  • 第一个可以称为关键字(key),每个关键字只能在map中出现一次;
  • 第二个可能称为该关键字的值(value);

map以模板(泛型)方式实现,可以存储任意类型的数据,包括使用者自定义的数据类型。Map主要用于资料一对一映射(one-to-one)的情況,map內部的实现自建一颗红黑树,这颗树具有对数据自动排序的功能。在map内部所有的数据都是有序的。

map的功能

自动建立key - value的对应。key 和 value可以是任意你需要的类型,包括自定义类型。

语法:

     C++ maps是一种关联式容器,包含 “关键字 / 值” 对

     begin()                  返回指向map头部的迭代器

     clear()                 删除所有元素

     count()                  返回指定元素出现的次数, (因为key值不会重复,所以只能是1 或 0)

     empty()                 如果map为空则返回true

     end()                     返回指向map末尾的迭代器

     equal_range()       返回特殊条目的迭代器对

     erase()                  删除一个元素

     find()                     查找一个元素

     get_allocator()      返回map的配置器

     insert()                  插入元素

     key_comp()          返回比较元素key的函数

     lower_bound()      返回键值>=给定元素的第一个位置

     max_size()           返回可以容纳的最大元素个数

     rbegin()                返回一个指向map尾部的逆向迭代器

     rend()                   返回一个指向map头部的逆向迭代器

     size()                   返回map中元素的个数

     swap()                 交换两个map

     upper_bound()    返回键值>给定元素的第一个位置

     value_comp()      返回比较元素value的函数

遍历map的方法

for(auto [x,c] : mp){
    
}

8、关闭同步流

ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);

二、题解

T1、

题目:STL3 - stack, queue, deque, priority_queue  C - 表达式求值

题解:

看到只有加号和乘号的时候,其实就会发现这一题不会很麻烦。而对于数字和符号,我们可以分别用以两个栈来存储它们。同时只要求输出答案的最后四位,所以我们可以在所有计算之后对10000取余。

困难与解决办法:

但是对于如何在一个字符串中,截取出数字放入栈中对我仍然是个难题。于是通过上网查询,我学到了函数stio()以及函数substr()。当然也可以以s[i] - '0'的形式逐个取出数字。

代码:

#include <iostream>
#include <stack>

using namespace std;

void jisuan(stack<int>& a, stack<char>& b) {
    int x = a.top();
	a.pop();
    int y = a.top();
	a.pop();
    char s = b.top();
	b.pop();
    if(s == '+'){
    	a.push((x + y) % 10000);
	}
    else{
    	a.push(x * y % 10000);
	}
}

int main()
{
    string s;
    cin >> s;
    stack<int> a;
    stack<char> b;
    
    for(int i = 0;i < s.size();i++){
        char x = s[i];
        if (x >= '0' && x <= '9'){
            int j = i;
            while (j < s.size() && s[j] >= '0' && s[j] <= '9'){
            	j++;
			}
            int x = stoi(s.substr(i, j - i)) % 10000;
            a.push(x);
            i = j - 1;
        }
		else if(x == '*'){
            while (b.size() && b.top() == '*'){
                jisuan(a, b);
            }
            b.push(x);
        } else if (x == '+'){
            while (b.size()){
                jisuan(a,b);
      		}
            b.push(x);
        }
    }

    while (b.size()){
    	jisuan(a,b);
	} 
    cout << a.top();
    return 0;
}

T2、

题目:练习题 D - Shifts and Sorting 

题解:

首先明确,本题就是要让 0都往前去,1都往后去,因此不难想到将一个由前面 x − 1个 1 与后面 1  个 0 组成的字符串搞好的最小的代价。显然是该串长度——首先证明可行,整段做一遍,0 到最前面,代价为长度 x;再证明最优,其它的方式无论怎么倒腾都不可能避免让每一个点都被移动过一次,那样答案就不可能比总长度更小。

所以我们先做一个字符串是s[ ],读入1和0串,再从左往右遍历。读到1的时候,记下索引 i,继续遍历,如果遍历到最后一个字符还是1,则结束。反之当读到0时,我们记下索引 j 。移动最后的0到最前面,把1一次往后移,这样一次的行为成本就是 j - i + 1。

代码:

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

int t;
string s;

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin >> t;
	while(t--){
		cin >> s;
		int len = s.length();
		s = " " + s;
		int f = 0;
		int ans = 0;
		for(int i = 1;i <= len;i++) {
			if (s[i] == '0' && f != 0) {
				swap(s[f], s[i]);
				ans += i - f + 1;
				for(int j = f + 1;j <= i;j++) {
					if (s[j] == '1') {
						f = j;
						break;
					}
				}
			}
			
			if (s[i] == '1' && f == 0) {
				f = i;
			}
		}
		cout << ans << "\n";
	}
	return 0;
}

T3、

题目:大一周六个人练习赛(2) A-B 数对

题解:

刚开始做的时候想着能无脑暴力枚举的,但是很快写完代码后就TLE了。于是我们想到要简化问题。求A - B = C 我们可以简化成A - C = B,只要找出有哪些数减去C之后等于B的,于是我们就想到了用map来做。

代码:

#include <bits/stdc++.h>
#include <map>
#include <string.h>
#define int long long

using namespace std;
const int N = 2e5 + 10;
int x[N];

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	int n,c,t = 0;
	cin >> n >> c;
	map<int,int> mp;
	for(int i = 0;i < n;i++){
		cin >> x[i];
		mp[x[i]] += 1;
		x[i] -= c;
	}
	for(int i = 0;i < n;i++){
		t += mp[x[i]];
	}
	cout << t;
	return 0;
}

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值