张桄玮
郑州一中(Legacy)
理解优先队列的一种实现方法: 二叉堆
使用STL
操作:
是一棵完全二叉树(最后一层从左往右依次排列中间不会空缺)
小根堆的情形:
既然知道了最多有2个节点, 就可以做一个简单的映射
好处: 简单, 紧凑; 坏处: 稀疏的时候占据大量无用空间
down(x)
把 \(x\)
往下调整: 不停地找到根左右之间的最小值, 把它与之交换up(x)
把 \(x\)
往上调整: 不停地与父亲节点比较, 如果父亲节点比较大,
就与父亲节点交换void push_up(int i, int val) {
while (i > 1 && val < heap[i / 2]) {heap[i] = heap[i / 2]; i /= 2;}heap[i] = val;
}
void push_down(int i, int val) {
int ch = i * 2;
while (ch <= size) {
if (ch < size && heap[ch + 1] < heap[ch]) ch++;if (val <= heap[ch]) break;
heap[i] = heap[ch];i = ch;ch *= 2;
}
heap[i] = val;
}
插入: 先放到最底下, 然后往上浮动
把根删了, 然后找一个节点顶上来, 往下移动到合适的位置.
heap[k]=heap[size];size--;down(k)或up(k);
heap[k]=x;down(k)或up(k);
思路: 开一个大根堆和小根堆
然后输出堆顶的元素即可.
题目大意
思考:
\[ \begin{aligned} A[1]+B[1] &\leq A[1]+B[2]&\leq &\cdots &\leq A[1]+B[N] \\ A[2]+B[1] &\leq A[2]+B[2]&\leq &\cdots &\leq A[2]+B[N] \\ && \vdots\\ A[N]+B[1] &\leq A[N]+B[2]&\leq &\cdots &\leq A[N]+B[N] \\ \end{aligned} \]
STL: 构建程序能够普遍受惠的标准库
标准库函数比大家多考虑的事情:
vector<pair<int, int> >
中的空格了!auto
代替
auto a=42; // a is of type int
int vals[]{1,2,3};
std::vector<int> v{1,2,3};
range-based for
循环
for(decl:coll){ stmt }
pair
有序对std::pair<TypA, TypB> p;
p.first
; 第二个元素:
p.second
.p=make_pair(val1, val2);
std::tie(ra, rb)=p
.tuple
不定数的值组std
命名空间tuple<Typ_1, Typ_2, ..., Typ_n> t;
Typ_i s = get<i>(t);
make_tuple("jyy", "NJU", 2024);
get<i>
的 \(i\) 要在编译期就决定tuple
里面写值就更复杂了. 直接摆烂!)struct
说
容器有三大类别:
序列式容器 – 链表/数组
array, vector, deque, list, forward_list
关联式容器 – 二叉树
set, multiset, map, multimap
无序容器 – Hash表
unordered_map,unordered_set
vector
vector<Type> vec;
vec.push_back(elem);
vec[i];
vec.size();
实现细节: 当发现不够的时候, 开一个更大的空间把数组的内容搬过去
deque
喜提 push_front
: 往前面插入元素
list
一些操作
set
(多重集合multiset
)依照他们的 “顺序” 排列(严格偏序)
x<y
, 一定没有y<x
x<y, y<z
\(\to\)
x<z
x<x
永远不成立a==b, b==c
\(\to\)
a==c
操作
map