算法小笔记0328
1
ios::sync_with_stdio(0);
ios::sync_with_stdio(false);
是 C++ 中用于关闭 C++ 输入输出流(iostream)与 C 输入输出库(stdio)同步的语句。默认情况下,C++ 的流库与 C 的stdio库是同步的,这意味着你可以混用 cin
, cout
和 scanf
, printf
等而不会出现问题。但是这种同步会导致性能下降,因为每个流库的操作都需要检查stdio库的状态。
当你设置 std::ios_base::sync_with_stdio(false);
时,你告诉 C++ 不必再与stdio库同步。这将提高输入输出操作的效率,特别是当你在程序中使用大量的 I/O 操作时。但是,这样做之后你就不能再保证 cin
, cout
和 C 的 scanf
, printf
混用时的正确性了。通常,在竞赛编程或者需要高性能 I/O 的场合,程序员会关闭同步,并使用 cin.tie(0);
进一步提高性能,因为这样可以解除 cin
和 cout
之间的绑定,使得 cin
和 cout
可以独立地、不按顺序地缓冲它们的 I/O 操作。
使用这个语句的典型场景是在程序的开头:这样做之后,你应该只使用 cin
和 cout
或者只使用 scanf
和 printf
,避免混用,以防止未定义行为。
2
cin.tie(0); cout.tie(0);
在 C++ 中,cin.tie()
和 cout.tie()
是与流对象的绑定相关的函数。默认情况下,cin
和 cout
是绑定的,这意味着当 cin
和 cout
同时用于输入和输出时,它们会保证输出的顺序与输入的顺序一致。这种绑定是为了让输出与输入保持同步,比如在交互式程序中,你希望在读取输入之前先看到所有的输出。
cin.tie(nullptr)
或 cin.tie(0)
的作用是取消 cin
和 cout
之间的绑定。这样,cin
的输入缓冲区和 cout
的输出缓冲区就可以独立地运作,不再需要等待对方。这通常可以提高 I/O 效率,特别是在进行大量 I/O 操作时。
同样地,cout.tie(nullptr)
或 cout.tie(0)
也可以用来取消 cout
的当前绑定。但是,通常你不需要这样做,因为 cout
默认就是与 cin
绑定的,而且取消 cin
的绑定通常也就意味着 cout
的绑定也被取消了。
3
priority_queue<int,vector<int>,greater<int>> h[100010]; //为每一家店创造一个优先队列(小顶对)
在 C++ 中,priority_queue<int, vector<int>, greater<int>> h[100010];
声明了一个包含 100010 个优先队列的数组 h
。每个优先队列都是使用 int
作为元素类型,vector<int>
作为底层容器,greater<int>
作为比较器的。
priority_queue
是 C++ 标准库中的一个容器适配器,它提供常数时间内的最大元素提取操作,即每次调用 pop
时移除的是队列中最大的元素,每次调用 top
时访问的是队列中最大的元素。默认情况下,priority_queue
是一个大顶堆,但是在这个声明中,通过使用 greater<int>
作为比较器,它被转换为一个一个小顶堆,即每次移除和访问的是队列中最小的元素。
vector<int>
是用于存储优先队列元素的底层容器,而 greater<int>
是一个函数对象,它定义了元素之间的比较方式。在这个例子中,greater<int>
会使得优先队列按照升序排列,即最小的元素在顶部。
这个声明的数组大小为 100010,这意味着你可以使用 h[0]
到 h[100009]
来访问数组中的每个优先队列。这在处理一些需要多个优先队列的问题时非常有用,例如在图论中的 Dijkstra 算法或者在某些数据结构中的多路归并问题。
4
sort(a+1, a+1+m, cmp);
在 C++ 中,sort(a+1, a+1+m, cmp)
是对标准库函数 std::sort
的一个调用,用于对数组 a
从第 a+1
个元素开始到第 a+m
个元素结束的子数组进行排序。这里的 cmp
是一个比较函数,用于定义排序的顺序。
std::sort
是 C++ 标准库中的算法,它位于 <algorithm>
头文件中。该函数使用快速排序算法的一个变体,其平均和最坏情况时间复杂度都是 O(n log n),其中 n 是要排序的元素数量。
这里的参数解释如下:
a+1
:指向要排序的子数组的起始元素的指针。由于数组索引是从 0 开始的,a+1
表示数组a
的第二个元素。a+1+m
:指向要排序的子数组的结束位置的后一个位置的指针。由于sort
的第二个参数是结束位置的后一个位置,所以a+1+m
表示从a+1
开始的第m
个元素之后的位置。cmp
:比较函数,用于确定排序的顺序。这个函数应该接受两个参数,并返回一个布尔值,表示第一个参数是否小于第二个参数。如果cmp
返回true
,则第一个参数会被放在第二个参数前面;如果返回false
,则第一个参数会被放在第二个参数后面。
下面是一个使用std::sort
的例子,包括一个简单的比较函数cmp
:
#include <iostream>
#include <algorithm>
// 比较函数,按升序排序
bool cmp(int a, int b) {
return a < b;
}
int main() {
int a[] = {4, 2, 5, 1, 3};
int m = 3; // 假设我们只想对数组的前 3 个元素进行排序
// 对数组的前 m 个元素进行排序
std::sort(a + 1, a + 1 + m, cmp);
// 输出排序后的数组
for (int i = 0; i < 5; ++i) {
std::cout << a[i] << ' ';
}
std::cout << std::endl;
return 0;
}
在这个例子中,数组 a
的第二个到第四个元素(索引为 1 到 3)会被排序,而第一个和最后一个元素(索引为 0 和 4)不会被排序。排序后的输出将是 4 1 2 5 3
。
5
bool operator < (const order &A)const{
return ti < A.ti;
}
在 C++ 中,operator<
是一个重载运算符函数,用于比较两个对象的大小关系。在您提供的代码片段中,operator<
被重载用于比较两个 order
类型的对象。这个运算符函数定义在 order
类的内部,并且被声明为 const
成员函数,这意味着它不会修改调用它的对象。
这个重载的 operator<
函数接受一个类型为 const order&
的参数 A
,表示要比较的另一个 order
对象。在这个函数中,ti
是 order
类的一个成员变量,用于确定两个 order
对象的顺序。如果当前对象的 ti
成员变量小于参数 A
的 ti
成员变量,函数返回 true
;否则返回 false
。
这种重载通常用于自定义类型,以便在标准库算法(如 sort
、priority_queue
等)中使用自定义比较逻辑。例如,如果您有一个 order
类型的对象数组,并且想要根据 ti
成员变量对数组进行排序,您可以这样做:
#include <iostream>
#include <vector>
#include <algorithm>
class order {
public:
int ti;
// 构造函数
order(int t) : ti(t) {}
// 重载 operator<
bool operator<(const order &A) const {
return ti < A.ti;
}
};
int main() {
vector<order> orders = {order(3), order(1), order(2)};
// 使用 sort 对 orders 数组进行排序
sort(orders.begin(), orders.end());
// 输出排序后的 orders
for (const auto &o : orders) {
cout << o.ti << ' ';
}
cout << std::endl;
return 0;
}
在这个例子中,sort
函数会使用 order
类中定义的 operator<
来比较 order
对象,并按照 ti
成员变量的值对它们进行升序排序。输出将是 1 2 3
。
6
memset(have,0,sizeof(have));
在 C++ 中,memset
是一个常用的库函数,用于将内存中的某一块区域全部设置为某个特定的值。它定义在 <cstring>
头文件中(在 C 语言中是 <string.h>
)。memset
的原型如下:
void *memset(void *s, int c, size_t n);
s
:指向要填充的内存块的指针。c
:要设置的值,该值以整数形式传递,但是函数会将该整数转换为无符号字符(unsigned char
)后再填充内存。n
:要填充的字节数。
在您提供的代码片段中,memset(have, 0, sizeof(have));
的作用是将have
所指向的内存区域中的前sizeof(have)
个字节全部设置为 0。这通常用于初始化数组或结构体的内存,确保所有位都被清零。
例如,如果您有一个整数数组int have[100];
,那么memset(have, 0, sizeof(have));
将会把数组have
中的所有元素都初始化为 0。
请注意,memset
应该用于对字节进行操作的情景,如果您想要将一个结构体或对象的内存全部设置为 0,这可能是一个合适的选择。但是,如果您想要将数组中的每个元素初始化为特定的值,而且这个值不是 0 或 -1,那么您应该使用其他方法,比如循环初始化或使用标准库函数std::fill
或std::fill_n
。这是因为memset
只能设置内存为 0 或 -1(由于填充的是字节,而不是整数或浮点数)。