NO.53十六届蓝桥杯备战|set和map|算法题|size|empty|begin|end|insert|erase|find|count|lower_bound|upper_bound(C++)

set/multiset

set 与 multiset 的区别: set 不能存相同元素, multiset 可以存相同的元素,其余的使⽤⽅式完全⼀致。因此,我们有时候可以⽤ set 帮助我们给数据去重。

创建set
#include <iostream>  
#include <set>  
using namespace std;  
int main()  
{  
	set<int> mp1;  
	set<string> mp2;  
	return 0;  
}
size/empty
  1. size :返回 set 中实际元素的个数。时间复杂度:O(1) 。
  2. empty :判断 set 是否为空。时间复杂度:O(1)
begin/end

迭代器,可以使⽤范围for遍历整个红⿊树。
遍历是按照中序遍历的顺序,因此是⼀个有序的序列

insert

向红⿊树中插⼊⼀个元素
时间复杂度:O(log N)

erase

删除⼀个元素
时间复杂度:O(log N)

find/count
  1. find :查找⼀个元素,返回的是迭代器。时间复杂度:O(log N) 。
  2. count :查询元素出现的次数,⼀般⽤来判断元素是否在红⿊树中。时间复杂度:O(log N)
    如果想查找元素是否在set中,我们⼀般不使⽤find,⽽是⽤count。因为find的返回值是⼀个迭代器,判断起来不⽅便
lower_bound/upper_bound
  1. lower_bound :⼤于等于x的最⼩元素,返回的是迭代器;
    时间复杂度:O(log N) 。
  2. upper_bound :⼤于x的最⼩元素,返回的是迭代器
    时间复杂度:O(log N)
所有测试代码
#include <iostream>  
#include <set>  
using namespace std;  
int a[] = {10, 60, 20, 70, 80, 30, 90, 40, 100, 50};  
int main()  
{  
	set<int> mp;  
	
	// 插⼊  
	for(auto x : a)  
	{  
	mp.insert(x);  
	}  
	
	// 遍历 set,最终的结果应该是有序的  
	for(auto x : mp)  
	{  
	cout << x << " ";  
	}  
	cout << endl;  
	// if(mp.count(1)) cout << "1" << endl;  
	// if(mp.count(99)) cout << "99" << endl;  
	// if(mp.count(30)) cout << "30" << endl;  
	// if(mp.count(10)) cout << "10" << endl;  
	// mp.erase(30);  
	// mp.erase(10);  
	// if(mp.count(30)) cout << "30" << endl;  
	// else cout << "no:30" << endl;  
	// if(mp.count(10)) cout << "10" << endl;  
	// else cout << "no:10" << endl;  
	auto x = mp.lower_bound(20);  
	auto y = mp.upper_bound(20);
	cout << *x << " " << *y << endl;  
	return 0;  
}

map/multimap

map 与 multimap 的区别: map 不能存相同元素, multimap 可以存相同的元素,其余的使⽤⽅式完全⼀致。
map 与 set 的区别: set ⾥⾯存的是⼀个单独的关键字,也就是存⼀个int 、char 、double或者string 。⽽ map ⾥⾯存的是⼀个 pair<key, value> ,(k-v模型)不仅有⼀个关键字,还会有⼀个与关键字绑定的值,⽐较⽅式是按照 key 的值来⽐较。
可以这样理解:红⿊树⾥⾯⼀个⼀个的结点都是⼀个结构体,⾥⾯有两个元素分别是 key 和 value 。插⼊、删除和查找的过程中,⽐较的是 key 的值。
⽐如,我们可以在 map 中:

  • <int, int> ,来统计数字出现的次数;
  • <string, int> ,来统计字符串出现的次数;
  • <string, string> ,表⽰⼀个字符串变成另⼀个字符串;
  • 甚⾄存 <int, vector<int>> 来表⽰⼀个数后⾯跟了若⼲个数…,⽤来存储树。
    因为模板这个强⼤的功能,使得 map 有很多⽤途,后⾯做题的时候再慢慢体会
创建map
#include <iostream>  
#include <vector>  
#include <map>  
using namespace std;  
int main()  
{  
	map<int, int> mp1;  
	map<int, string> mp2;  
	map<string, int> mp3;  
	map<int, vector<int>> mp4; // 甚⾄可以挂⼀个 vector
	return 0;  
}
size/empty
  1. size :求红⿊树的⼤⼩。时间复杂度:O(1)
  2. empty :判断红⿊树是否为空。时间复杂度:O(1)
begin/end

迭代器,可以使⽤范围for遍历整个红⿊树。
遍历是按照中序遍历的顺序,因此是⼀个有序的序列

insert

向红⿊树中插⼊⼀个元素。这⾥需要插⼊⼀个pair,可以⽤ {} 形式。⽐如: mp.insert({1, 2})
时间复杂度:O(log N)

operator[]

重载[],使的map可以像数组⼀样使⽤。
这是map最好⽤的接⼝,有了这个重载,map的使⽤就变得特别轻松,不⽤写很多冗余的代码。
它的底层其实就是调⽤了insert函数,并且会返回val的引⽤。

erase

删除⼀个元素。
时间复杂度:O(log N)

find/count
  1. find :查找⼀个元素,返回的是迭代器。时间复杂度:O(log N) 。
  2. count :查询元素出现的次数,⼀般⽤来判断当前元素是否在红⿊树中。时间复杂度:O(log N)
lower_bound/upper_bound
  1. lower_bound :⼤于等于x的最⼩元素,返回的是迭代器。时间复杂度:O(log N) 。
  2. upper_bound :⼤于x的最⼩元素,返回的是迭代器。时间复杂度:O(log N)
所有测试代码
#include <iostream>  
#include <map>  
using namespace std;  
void print(map<string, int>& mp)  
{  
	for(auto& p : mp)  
	{  
	cout << p.first << " " << p.second << endl;  
	}  
}  

// 统计⼀堆字符串中,每⼀个字符串出现的次数  
void fun()  
{  
	string s;  
	map<string, int> mp; // <字符串,字符串出现的次数>  
	for(int i = 1; i <= 10; i++)  
	{  
		cin >> s;  
		mp[s]++; // 体现了 operator 的强⼤
		//如果mp里没有s,先插入一个s,在给v++  
	}  
	print(mp);  
}

int main()  
{  
	fun();  
	// map<string, int> mp;  
	// // 插⼊  
	// mp.insert({"张三", 1});  
	// mp.insert({"李四", 2});  
	// mp.insert({"王五", 3});  
	// // print(mp);  
	// // operator[] 可以让 map 像数组⼀样使⽤  
	// cout << mp["张三"] << endl;  
	// mp["张三"] = 110;  
	// cout << mp["张三"] << endl;  
	// // 注意事项:operator[] 有可能会向 map 中插⼊本不想插⼊的元素  
	// // [] ⾥⾯的内容如果不存在 map 中,会先插⼊,然后再拿值  
	// // 插⼊的时候:第⼀个关键字就是 [] ⾥⾯的内容,第⼆个关键字是⼀个默认值  
	// if(mp.count("赵六") && mp["赵六"] == 4) cout << "yes" << endl;  
	// else cout << "no" << endl;  
	// // 删除  
	// mp.erase("张三");  
	// print(mp);  
	return 0;  
}

红⿊树的算法题

P2786 英语1(eng1)- 英语作文 - 洛谷

把所有高级词汇,含金量绑定,放在map中,读取英语作文,每读取一个英语单词的时候,就去map里找含金量

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

typedef long long LL;
int n, p;
map<string, int> mp;

bool check(char ch)
{
    if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
    {
        return true;
    }
    else
        return false;
}

int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0);

    cin >> n >> p;
    for (int i = 1; i <= n; i++)
    {
        string s; int x;
        cin >> s >> x;
        mp[s] = x;
    }
    
    LL ret = 0;
    char ch;
    string t = "";
    
    while (scanf("%c", &ch) != EOF)
    {
        if (check(ch)) t += ch;
        else
        {
            ret = (ret + mp[t]) % p;
            t = "";
        }
    }
    cout << ret << endl;
    return 0;
}
P2234 [HNOI2002] 营业额统计 - 洛谷

针对每一天的营业额x,找出前面的数中,哪个数离他最近
大于等于x的最小值y
小于等于x的最大值z
对y-x和z-x的绝对值取min

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

const int INF = 1e7 + 10;
int n;
set<int> mp;

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

    cin >> n;
    int ret; cin >> ret;
    mp.insert(ret);
    
    //左右边界
    mp.insert(-INF); mp.insert(INF);

    for (int i = 2; i <= n; i++)
    {
        int x; cin >> x;
        
        auto it = mp.lower_bound(x);
        auto tmp = it;
        tmp--;

        if (*it == x) continue;

        ret += min(abs(*tmp - x), abs(*it - x));
        mp.insert(x);
    }
    cout << ret << endl;
    
    return 0;
}
P5250 【深基17.例5】木材仓库 - 洛谷
#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const LL INF = 1e10 + 10;

set<LL> mp;

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

    int q; cin >> q;

    //处理边界
    mp.insert(-INF); mp.insert(INF);
    
    while (q--)
    {
        LL op, len; cin >> op >> len;
        if (op == 1)
        {
            if (mp.count(len)) cout << "Already Exist" << endl;
            else mp.insert(len);
        }
        else
        {
            //找最近的那个
            if (mp.size() == 2)
            {
                cout << "Empty" << endl;
            }
            else
            {
                auto it = mp.lower_bound(len);
                auto tmp = it;
                tmp--;

                if (abs(*tmp - len) <= abs(*it - len))
                {
                    cout << *tmp << endl;
                    mp.erase(tmp);
                }
                else
                {
                    cout << *it << endl;
                    mp.erase(it);
                }
            }
        }
    }
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值