sort
数组从1开始的整型排序:
inline bool cmp(const int a, const int b) {
return xx[a] < xx[b];
}
sort(a + 1, a + 1 + n, cmp);
结构体排序:(结构体是poi)
inline bool cmp(const poi &a, const poi &b) {
if (a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
注意这个重载运算符或者是比较函数里面,相等的时候不能返回一。是由于一个“强弱规则”规定的。
queue
一个队列。
queue<int> q;
q.push(233);
q.pop();
printf("%d\n", q.front());
q.empty()
别忘了每次使用前清空while(!q.empty())q.pop();
stack建议手写
priority_queue
实现堆的功能。
typedef pair<LL, int> PII;
priority_queue<PII, vector<PII>, greater<PII>> q; //这是常见的dijkstra的形式
inline bool operator < (const poi &a, const poi &b) {
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
priority_queue<poi> //这里实现了一个结构体堆
注意优先队列里面定义的优先级高的先出队。重载运算符的话,小于号返回一的情况的元素优先出队。
vector
最灵活的STL。
vector<int> a;
尾部插入:a.push_back(1);
尾部删除:a.pop_back();
返回大小:a.size();
//注意下标从0到size-1。
支持方括号:a[2] = 1; printf("%d\n", a[2]);
方便排序:sort(a.begin(), a.end(), cmp);
支持清空:a.clear();
支持间赋值:vector<int> b; b = a;
支持在一个位置处插入值:a.insert(a.begin(), 1)
就是在开头插入一个1,原来的都向后移动。 注意这个时候迭代器指向的值就发生了变化。注意这个位置必须是一个地址,地址=下标+a.begin()
vector<int> q(10);
int main() {
q[0] = 0; q[1] = 3; q[2] = 2; q[3] = 2; q[4] = 5;
q.insert(3 + q.begin(), 44);
for (int i = 0; i < q.size(); ++i)
printf("%d ", q[i]);
return 0;
}
注意这个玩意只支持一个一个的扩展,如果直接写a[0]=1;
是会RE的,但是如果我们先插入一个数,再执行a[0]=1
,就好了。
可以一开始指定大小:vector<int>a(10);
,这样的话就可以直接访问
a
[
0
]
,
a
[
1
]
a[0],a[1]
a[0],a[1]等元素了。
支持在一个位置删除值:a.erase(a.begin()+1)
就是删除下标为1的这个元素,后面的整体前移。
如果 i n s e r t insert insert, e r a s e erase erase和二分在一起用的话。可以代替 s e t set set/平衡树的一些操作。
set
set的内部是一个红黑树。要求set内部的值唯一。
set<int>q;
支持插入:q.insert(1);
,这个insert是有返回值的。它是一个pair, 它的second位记录的是是否插入成功(如果之前有就不成功。)
支持查询一个键值是否出现过:q.count(1);
支持删除:q.erase(1); q.erase(it);(it为迭代器)
注意他是不检查是否合法的,比较容易RE
支持清空:q.clear()
支持查询一个键值的迭代器:q.find(1);
支持查询lower_bound和upper_bound。q.lower_bound(2);
返回一个迭代器。它的键值大于等于2且最小。如果找不到的话,就会返回a.end()
不支持方括号,不支持直接修改一个元素的值!要修改只能先删后加!
注意set的end是有实际的值的。所以存储的范围是[begin(),end()]。lower_bound返回end并不能说明不存在。最后要再判断一下
set可以支持前驱,后继。但是不支持排名。
前驱:
set<int>::iterator it = q.lower_bound(x);
--it;
后缀:
set<int>:: iterator it = q.upper_bound(x);
(这里不存在会返回end)
multiset
多重集,允许一个元素出现多次。
multiset<int>s;
支持查询一个元素出现的个数:s.count(key);
复杂度log
支持删除等于一个元素的所有元素:s.erase(key);
支持删除一个区间的元素:s.erase(l,r)
。这里l,r都是迭代器,删除了[l,r-1]的这些元素。
支持查找一个 元素第一次出现的迭代器:s.find(key)
。
注意multiset里面最后一个元素不是end,是end的前一个元素了
map
map可以看做是一个映射,它把两种数据类型联系到了一起。可以看成hash表。
如果是结构体的映射的话,需要重载’<'运算符。
struct poi {
int x, y;
poi(){}
poi(int x_, int y_){x = x_; y = y_;}
};
inline bool operator < (const poi &a, const poi &b) {
return (a.x == b.x) ? (a.y < b.y) : (a.x < b.x);
}
map<poi, int> q;
unordered_map(c++11)
顾名思义就是不带内部排序的map。所以插入删除是O(1)的。就是一个强大的hash表了吧。不过这东西如果第一维存一个结构体比较麻烦。需要自己重载等于号和算hash值的函数
struct poi {
int x, y;
poi(){}
poi(int x_, int y_){x = x_; y = y_;}
};
struct getha {
size_t operator () (const poi &a) const {
return a.x * 100 + a.y;
}
};
inline bool operator == (const poi &a, const poi &b) {
return (a.x == b.x) && (a.y == b.y);
}
unordered_map<poi, int, getha> q;
deque
双端队列
deque<int> q;
支持后端插入:q.push_back(1);
支持后端删除:q.pop_back();
支持前端插入:q.push_front(1);
支持前端删除:q.pop_front();
常数差不多是tm的
O
(
1
)
O(1)
O(1)的40倍。巨大无比
(普通的queue的常数差不多是
O
(
1
)
O(1)
O(1)的7倍)(这里使用赋值来定义
O
(
1
)
O(1)
O(1))
bitset
bitset把32个0-1二进制位压成一个整数处理。复杂度可以除以32。
(右边是低位,左边是高位)
bitset<N>a;
支持[]
运算符:a[0]=1; a[1] =0;
支持所有的位运算符:a ^= 1;
a <<= 1
rope( 可持久化线段树? C++11
https://www.cnblogs.com/scx2015noip-as-php/p/rope.html
rope<char>q;
可以看做一个功能更加强大的字符串类型。
它支持在任意位置添加一个串,任意位置删除,任意位置替换。
rope<int>q;