日日新之STL
map容器的erase操作(map会根据key值进行默认排序,map删除可以根据迭代器或key值)
#include <iostream>
#include <map>
using namespace std;
const int N=105;
int main(){
map<int,string> mp;
mp[1]="123";
mp.insert({2,"222"});
mp.insert({3,"222"});
mp.erase(mp.begin());
// mp.erase(1);效果相同
// map的erase函数里面,既可以是值也可以是迭代器
for(map<int,string>::iterator it=mp.begin();it!=mp.end();it++){
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}
三、蒟蒻(map容器的删除操作)
#include <iostream>
#include <map>
#include <algorithm>
#define int long long
using namespace std;
//const int N=1e5+5;
map<int,int> mp1;//既然要按照两个标准分别排序,那就分别用两个容器存
//方便分别找到两个标准下的最小值,删去某个商品时两个容器中都要删去
map<int,int> mp2;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
int op,w,t;
cin>>op;
if(op==1){
cin>>w>>t;
if(mp1.count(w)==0&&mp2.count(t)==0){
mp1.insert({w,t});
mp2.insert({t,w});
}
}
else if(op==2){//删除w最小的商品,在mp1中排在最前
mp2.erase(mp1.begin()->second);
mp1.erase(mp1.begin());
// mp2.erase(mp1.begin()->second);顺序绝对不能反呀!
//删除了mp1.begin那么下一次访问mp1.begin就不是当初的那个了
}
else if(op==3){
mp1.erase(mp2.begin()->second);
mp2.erase(mp2.begin());
// mp1.erase(mp2.begin()->second);
}
}
int res=0;
// for(auto x:mp1)res+=x.first;
for(map<int,int>::iterator it=mp1.begin();it!=mp1.end();it++)res+=it->first;
cout<<res;
return 0;
}
对于cpp中string类型的比较函数str1.compare(str2)或者是直接==,>,<,比较长度不一样的字符串要先讨论长度
对于cpp中string类型的比较函数str1.compare(str2)或者是直接==,>,<,都只是顺序按照字典序比较。
一旦比出高下就返回比较结果。如果此时两个字符串的长度不相等,那结果就很尴尬了,很有可能更长的字符串比出来结果更小。
传送门
#include<bits/stdc++.h>
using namespace std;
#include <string.h>
int main(){
int n;
cin>>n;
string str;
int pos;
for(int i=1;i<=n;i++){
string s;
cin>>s;
// if(s>str){
if(s.size()>str.size())
{
str=s;
// str.assign(s);
pos=i;
}
else if(s.size()==str.size()){
if(s.compare(str)>0){
str=s;
pos=i;
}
}
else continue;
// cout<<i<<" "<<s<<" "<<str<<" "<<endl;
}
cout<<pos<<endl;
cout<<str<<endl;
return 0;
}
如果只通过compare或者> 来判断,就过不了这个样例
5
98765
12365
87954
1022356
985678
来个例子
鹅鹅鹅,虽然这道题完全没必要这样,因为作妖还超时了,主要是想练一下 在字符串中查找某字符出现次数的STL做法
C++ 计算一个字符串中子串出现的次数
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
string s;
while(t--){
int index=0;
int x,y,z;
// cin>>s;
getline(cin,s);//可以读入带有空格的一行字符串
int len=s.size();
while(index=s.find("A",index)<len){
x++;
index++;
//注意 比如 1、erase函数删除某字串后指向的是该字串后的那个字符
//2、find函数只能找"A"不能找'A',函数原型是string类型 ,
//3、find(str,index)是从下标index开始找,找到后返回的是这个字符所在位置,
//下一次自然从后一个字符找
}
index=0;
while(index=s.find("B",index)<len){ //下标index开始找,下标不能超过len
y++;
index++;
}
index=0;
while(index=s.find("C",index)<len){
z++;
index++;
}
//AB BC
if(x+z==y)printf("YES\n");
else printf("NO\n");
}
}
C++中字符串查找
s.find(s1) //查找s中第一次出现s1的位置,并返回(包括0)
s.rfind(s1) //查找s中最后次出现s1的位置,并返回(包括0)
s.find_first_of(s1) //查找在s1中任意一个字符在s中第一次出现的位置,并返回(包括0)
s.find_last_of(s1) //查找在s1中任意一个字符在s中最后一次出现的位置,并返回(包括0)
s.fin_first_not_of(s1) //查找s中第一个不属于s1中的字符的位置,并返回(包括0)
s.fin_last_not_of(s1) //查找s中最后一个不属于s1中的字符的位置,并返回(包括0)
现用现查系列
vector, 变长数组,倍增的思想
vector<int> a(10,0);//容量,初始化
size(),时间复杂度为O(1),empty()——所有容器都有
clear() 清空,并非所有元素都有,比如队列和stack就没有
系统为某一程序分配空间时,所需时间与空间大小无关,与申请次数有关
一次申请长度为1000的数组和1000次申请长度为1的数组,花费时间后者可能是前者1000倍
对于变长数组,要尽量减少申请次数,但是可以浪费空间
front()/back()
push_back()/pop_back()
begin()/end()迭代器,可以看做指针
for(vector<int>::iterator it=a.begin();it!=a.end();it++)cout<<*it;
for(auto x:a)cout<<x;
[] 访问元素
黑科技:支持比较运算,按字典序
auto x:a可以遍历所有容器
pair<int, string> 二元组 ,相当于自带一个结构体而且附赠比较函数
first, 第一个元素
second, 第二个元素
支持比较运算,以first为第一关键字,以second为第二关键字(字典序)
typedef pair<int, string> pii;
pii p={6,"xyj"};
pii p2=make_pair(6,"xyj");
bool cmp(pii p1,pii p2){//改成以第二关键字排序
return p1.second>p2.second;
}
string,字符串
size()/length() 返回字符串长度,char字符数组是strlen
empty()
clear()
substr(起始下标,(子串长度)) 返回子串
C++语言里面第二个参数是长度,其他很多语言比如Java都是首尾下标
c_str() 返回字符串所在字符数组的起始地址
string a="abcd";a+="efgh";
printf("%s",c_str(a));
queue, 队列
size()
empty()
queue<int> q;
q=queue<int>();//不能用clear函数清空,重新构造一个就ok
push() 向队尾插入一个元素
front() 返回队头元素
back() 返回队尾元素
pop() 弹出队头元素
priority_queue, 优先队列,默认是大根堆
size()
empty()
push() 插入一个元素
top() 返回堆顶元素
pop() 弹出堆顶元素
定义成小根堆的方式:priority_queue<int, vector<int>, greater<int>> q;
或者用黑科技:Q.push(-x)
deque, 双端队列,加强版的vector(多了push_front)一般不用,效率低到令人发指
size()
empty()
clear()
front()/back()
push_back()/pop_back()
push_front()/pop_front()
begin()/end()
[]
set, map, multiset, multimap, 基于平衡二叉树(红黑树),==动态维护有序序列==
size()
empty()
clear()
begin()/end()
++, -- 返回前驱和后继,时间复杂度 O(logn)
set/multiset
set不能有重复元素,插入重复元素的操作会被忽略掉
以下所有操作时间复杂度都是O(logn)
insert() 插入一个数
find() 查找一个数
count() 返回某一个数的个数
erase()
(1) 输入是一个数x,删除所有x O(k + logn)
(2) 输入一个迭代器,删除这个迭代器
lower_bound()/upper_bound()
lower_bound(x) 返回大于等于x的最小的数的迭代器
upper_bound(x) 返回大于x的最小的数的迭代器
map/multimap
insert() 插入的数是一个pair
erase() 输入的参数是pair或者迭代器
find()
[] 注意multimap不支持此操作。 时间复杂度是 O(logn)
lower_bound()/upper_bound()
unordered_set, unordered_map, unordered_multiset, unordered_multimap, 哈希表
和上面类似,增删改查的时间复杂度是 O(1)
不支持 lower_bound()/upper_bound(), 迭代器的++,--
bitset, 圧位
c++里bool类型是一个字节
bitset<10000> s;
~, &, |, ^
>>, <<
==, !=
[]
count() 返回有多少个1
any() 判断是否至少有一个1
none() 判断是否全为0
set() 把所有位置成1
set(k, v) 将第k位变成v
reset() 把所有位变成0
flip() 等价于~
flip(k) 把第k位取反