0%

C++ 与 STL

b站视频链接:北京理工大学ACM冬季培训课程
课程刷题地址 2020 BIT冬训-C++STL
本篇博文为看视频学习时的记录与自己的一些总结
学习笔记合集:算法入门基础

  • C++ 与 STL
    • hello world program
      • C 与 C++ 的区别
      • Visual Studio
      • hello world
    • 基本数据类型、输入输出
    • C++ 语法特性
      • 新的基本类型 bool
      • 动态开辟内存
      • 引用
      • 函数重载
      • 结构体
      • C++11 新的特性
    • C 标准库函数与 C++STL
      • C 标准库常用函数回顾
        • <cstring>
        • <cmath>
        • <cstdlib>
        • <ctime>
        • <ctype>
      • C++STL <vector>
      • C++STL <string>
      • C++STL <algorithm>
        • sort
        • 其他 algorithm 函数
      • 其他
        • <stack> 栈
        • <queue> 队列
        • <set> 集合
        • <map> 映射
        • <bitset>
        • 其他中的其他
    • 细节上的一点东西
      • 竞赛细节
      • 日常练习
    • 在线评测系统(Online Judge, OJ)

C++ 与 STL

hello world program

C 与 C++ 的区别

C:操控一切过程与细节
C++:有一套STL
打ACM用? C with C++STL

Visual Studio

1
2
3
#define _CRT_SECURE_NO_WARNINGS   //从 scanf_s 到 scanf
#include<bits/stdc++.h>
//这是万能头 but VS 莫得 就用不了 Dev-C++ 或可用

hello world

1
2
3
4
5
6
7
8
9
10
11
12
#include<iostream>
//C:#include<stdio.h> C++:#include<cstdio>
using namespace std; //用标准库里的东西:std:: 这里可以是std::cout

int main(){ //C++:cout C:printf
cout<<"hello world!"<<endl; //这里endl与'\n'在细节上略有不同
return 0; //养成return 0;的好习惯
}
/*
说一下命名:不能与库函数冲突
prev next count >> pre nxt cnt
*/

基本数据类型、输入输出

int
char
bool
char*
string

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

输出就是刚刚的cout
输入 C++:cin C:scanf cout用'<<' cin用'>>' 表示数据流的方向
C++里面没有"%d","%s","%c":所有标准数据类型都可以用cin输入
并不是说C++没有输入输出格式控制,只是在这里并不会讲什么



cin.getline(); //报错?得是指针!
getline();



文件输入输出 cin判断EOF
C:scanf("%d",&a)!=EOF;
C++:while(cin>>a){...}



cin的速度比scanf慢不少
1e5以上的数据用cin读入可能TLE(Time Limit Exceeded)
此时建议用scanf



输出小数用printf更方便
C++格式输出要用<iomanip>头文件
cout.setprecistion(int digit)来修改精度

C++ 语法特性

新的基本类型 bool

true/false 两个值
true:真:非0 / false:假:0

1
2
3
bool yes=true;
if(yes) puts("yes");
else puts("no");

动态开辟内存

1
2
3
4
5
6
7
8
9
10
C++:用new来动态开辟内存
int* number = new int;
int* arr = new int[100];
int* carr = (int*)malloc(100 * sizeof(int));

C:
malloc(1000);

释放内存:delete();
平时写题的代码可以不用释放内存。

这位北理的学长说 C++ 不支持变长数组,但C语言支持,想起当时在学校里用 VC++6.0 学C的时候好像也不支持,于是我用VS2019试了试,好像也不行:

1
2
3
4
5
#include<stdio.h>
int main() {
int num = 10;
int arr[num];
}

就这样,还是有一条清晰的红色波浪线摆在arr[num]的num下边。
但是,此时弹幕大神说到:C99支持Variable Length Array
那么就是说我们可以在C99标准下使用变长数组emmm…
具体参见:C99中的变长数组

引用

C++中用 & 来创建引用,可把其当作不能改变指向对象的指针

1
2
3
4
5
6
7
void swapInt(int& a, int& b)        //在C语言里干不了的经典事件
{
int c = a;
a = b;
b = c;
}

引用多数情况下在函数传递参数的时候才会用到,以简化指针的代码

1
2
3
int number = 10;
int& a = number;
int* b = &number;

函数重载

C++中,函数是以函数名+参数列表来区分的
两个函数可以名字相同,但是参数列表和返回值不同

1
2
void add(int a, int b){...}
void add(int b){...}

函数的部分参数可以缺省,没有提供参数时用缺省值代替

1
2
3
4
void add(int a, int b = 0){...}
...
add(1); //1,0
add(1 + 2); //1,2

结构体

1
2
3
4
5
6
7
8
9
10
11
12
C:
typedef struct node //C++typedef可省
{...}Node;
struct node; //C++struct可省

C++:
struct node
{
int number;
node* next;
};
node* head; //可以直接使用结构的名字

struct中可以加入与结构同名,无返回值的构造函数
在创建struct时会自动调用构造函数
与缺省参数配合使用,使代码更简洁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct node
{
int number;
node* next;
node(int _number = 0, node* _next = NULL) //使用构造函数
{
number = _number;
next = _next;
}
};

int main(){
node a = node(0);
node* b = new node(1, &a);

C++11 新的特性

新型 for 循环:只需给出变量和要迭代的区间

1
2
for(数据类型 x: 数据集)
for(数据类型 &x: 数据集)

auto 自动类型推导

1
2
std::vector<int>::iterator iter = v.begin();
auto iter = v.begin();

C 标准库函数与 C++STL

C++ 标准库
重点:<vector> <string> <algorithm>
以后:<queue> <stack> <set> <map> <bitset> <functional> <complex>

C 标准库常用函数回顾

<cstring>

1
2
3
4
5
6
7
8
9
<cstring>   //C Language: <string.h>
strlen(); //字符串长度
strcmp(); //字符串比较
strcpy(); //字符串拷贝
memset(); //暴力清空(赋值)
memcpy(); //暴力拷贝

/*-----常用初始化函数-----*/
memset(str, 0, sizeof(str)); //0可换为-1、0x3f3f3f3f

这些都很基础,应该还是得记一记
废话不多说,直接上文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
std::strlen                                 //注意strlen与sizeof的区别
std::size_t strlen( const char* str );
Parameters: str - pointer to the null-terminated byte string to be examined
Return value: The length of the null-terminated string str.

/*-----strlen与sizeof-----*/
sizeof运算符指出的是整个数组的长度;
strlen返回的是存储在数组中的字符串的长度,而非数组本身长度
strlen只计算可见字符,而不会包含结束字符‘\0'
存储字符串到字符数组中要求数组长度至少为字符串长度strlen+1
字符串以‘\0'为结束标志
/*----------*/

std::strcmp
int strcmp( const char *lhs, const char *rhs );
Parameters: lhs, rhs - pointers to the null-terminated byte strings to compare
Return value:
Negative value if lhs appears before rhs in lexicographical order. //小于
Zero if lhs and rhs compare equal. //等于
Positive value if lhs appears after rhs in lexicographical order. //大于

std::strcpy
char* strcpy( char* dest, const char* src );
Parameters
dest - pointer to the character array to write to
src - pointer to the null-terminated byte string to copy from
Return value
dest

std::memset
void* memset( void* dest, int ch, std::size_t count );
Parameters
dest - pointer to the object to fill
ch - fill byte
count - number of bytes to fill
Return value
dest

std::memcpy
void* memcpy( void* dest, const void* src, std::size_t count );
Parameters
dest - pointer to the memory location to copy to
src - pointer to the memory location to copy from
count - number of bytes to copy
Return value
dest

<cmath>

1
2
3
<cmath>
pow(); sin(); cos(); tan();
asin(); acos(); atan(); ...

<cstdlib>

1
2
3
4
<cstdlib>
qsort(); //C语言快排
rand(); //随机数
malloc(); free(); //C语言动态分配内存

<ctime>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<ctime>
time();
/*-----From C++ reference-----*/
#include <ctime>
#include <iostream>

int main()
{
std::time_t result = std::time(nullptr);
std::cout << std::asctime(std::localtime(&result))
<< result << " seconds since the Epoch\n";
}

OUTPUT:
Wed Sep 21 10:27:52 2011
1316615272 seconds since the Epoch
/*----------------------------*/
还可配合随机数使用:
/*-----From C++ reference-----*/
#include <cstdlib>
#include <iostream>
#include <ctime>

int main()
{
std::srand(std::time(0)); //use current time as seed for random generator
int random_variable = std::rand();
std::cout << "Random value on [0 " << RAND_MAX << "]: "
<< random_variable << '\n';
}

Possible output:
Random value on [0 2147483647]: 1373858591
/*----------------------------*/

clock(); //程序启动到目前位置的毫秒数

<ctype>

1
2
3
4
<ctype>
isdigit(); //判断字符是否为数字
isalpha(); //判断字符是否大小写字母
...

C++STL <vector>

1
2
3
4
vector<int> arr0;           // 初始化一个 size 为 0 的 vector
vector<int> arr1[100]; // 初始化一百个默认值为 0 的元素
int arr2[100]; // 普通整型数组
vector<int> arr3(10, 1); // 初始化十个值为 1 的元素

vector 可以被看成一个“超级数组”
可以像链表一样动态改变长度

1
2
vector<int> list;
list.push_back(1);

vector 的遍历(输入)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
vector<int> arr(100);
vector<int> list;
for(int i = 0; i < 100; i++)
{
scanf("%d", &arr[i]);
cout << arr[i] << endl;
}
for(int i = 0; i < 100; i++)
{
int a;
cin >> a;
list.push_back(a);
printf("%d\n", list[i]);
}

遍历

1
int i = 0; i < arr1.size(); i++;

与普通的数组类似,vector 也可以使用指针来访问遍历每一个元素,
STL 中的指针被称为迭代器(iterator)

迭代器:遍历容器中数据的对象。对存储于容器中的数据进行处理时,迭代器能按预先定义的顺序从一个成员移向另一个成员。

也就是说,通过迭代器可以在不了解容器内部原理的情况下遍历容器

1
2
3
4
vector<int>::iterator p1;
for (p1 = arr1.begin(); p1 != arr1.end(); p1++) //朴实枯燥
//注意arr1.end()为最后一个元素的下一个元素的地址
for (p = str; *p; p++) //花里胡哨

常见操作:

1
2
3
4
5
6
7
8
9
10
11
12
list.size();        //获得元素个数          O(1)
// 实际元素个数,不是容量
list.clear(); //一键清空 O(n)
list.empty(); //是否为空 O(1)
list.begin(); //首元素的迭代器 O(1)
list.end(); //最后一个的下一个元素 O(1)
//(实际并不存在的)
list.erase(p1); //删p1位置 O(n)
list.push_back(); //往后加元素 O(1)
list.pop_back(); //删最后一个元素 O(1)
reverse(list.begin(), list.end());
// 翻转向量 O(n)

C++STL <string>

string 可看成一个特殊的 vector
string $\Longleftarrow$ C 语言字符串
vector $\Longleftarrow$ 普通数组

初始化:

1
2
string str1 = "hello";
char str2[] = "world";

vector 的操作 string 基本都有
唯一区别是 size 的复杂度
所有参数为字符串的地方既可以是 string
也可以是 C 字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
string str = "hello";
str.length(); str.size(); // O(n)
str.insert(n, "aaa"); // 在下标为 n 处插入一个字符或字符串 O(n)
// str.insert(n, 3, 'a');
str.insert(str.begin(), 'a');
str.erase(n, m); // 删除 string 对象中的子串
str.erase(n); // 从 n 开始删到最后
str.c_str(); // 返回 C 语言字符串,用于 printf O(n)
str.append(str2); // 把 str2 拼接到 str 后面 O(n)
str.compare(str2); // strcmp(str, str2);
str == str2; // strcmp(str, str2) == 0;
str += str; // str.append(str2);
str += 'a'; // str.push_back('a');

可以使用 + 和 += 运算符对 string 对象执行字符串的连接操作,可以用 <、<=、==、!=、 >=、> 运算符比较 string 对象

substr 成员函数可以用于求子串 (n, m);
调用时,若省略 m 或 m 超过了字符串的长度,则求出来的字串就是从下标 n 开始一直到字符串结束的部分

交换两个 string 对象的内容:swap
查找子串位置 find

用 STL 算法操作 string 对象:

1
2
3
4
5
6
7
string s("afgcbed");
sort(s.begin(), s.end());
cout << s << endl; // 输出 abcdefg
next_permutation(s.begin(), s.end());
cout << s << endl; // 输出 abcdegf
reverse(s.begin(), s.end()); // 翻转字符串
cout << s << endl; // 输出 fgedcba

C++STL <algorithm>

定义了很多经常使用的算法,极大地简化了代码量

sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <algorithm>
sort(); //快排(默认升序)
void sort<_Ranlt> (const _Ranlt_First, const _Ranlt_Last)
//第一个参数是数组的头指针,另一个参数是最后一个元素的下一个元素的指针
//O(nlogn)
/*-------------------------*/
int arr[] {2, 3, 1, 5, 4};
int n = 5;
sort(arr, arr + n);
for (int i = 0; i < n; i++){
// 1 2 3 4 5
printf("%d\n", arr[i]);
}
/*-------------------------*/
vector<int> arr;
sort(arr.begin(), arr.end());

和 C 语言 qsort 一样,sort 可以使用自定义的比较函数
比较函数参数是两个待比较变量,返回值是比较的 bool 值

1
2
3
4
bool cmpInt(int a, int b){
return a > b;
}
sort(arr.begin(), arr.end(), cmpInt);

内部排序函数是按小于关系来的,排序结果是升序
如果像上图一样按大于关系比较,则可以得到降序的排序结果

自己定义的结构体一定要写比较函数!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Point
{
int x, y;
};
Point points[1111];
bool cmp(Point a, Point b) //你可以给自己的结构体钦定一个小于关系
{
if (a.x != b.x)
{
return a.x < b.x;
}
return a.y < b.y;
}

int main(){
sort(points, point + 10, cmp);

把刚刚的 cmp 改名成 operator< 后,你就可以像整数一样用小于号来比较两个结构体了
由于 sort 默认使用的是小于关系,sort 默认使用的函数也可以省略不写了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct Point
{
int x, y;
};
Point points[1111];
bool operator<(Point a, Point b)
{
if (a.x != b.x)
{
return a.x < b.x;
}
return a.y < b.y;
}

int main(){
sort(points, point + 10);
points[0] < points[111];

其他 algorithm 函数

最大最小值

1
min(1, 2);  max(1, 2);  // O(1)

数组最大最小指针

1
2
3
min_element(arr.begin(), arr.end());
max_element(arr.begin(), arr.end());
// O(n)

把数组中第 n 小(n 从 0 开始算)的数放到第 n 个位置
类似快排,并且保证它左边的数比它小,右边的数比它大
即能保证 n 在正确的位置:arr.begin()+n

1
nth_element(arr.begin(), arr.begin() + n, arr.end());   // O(n)

交换任意两个同类型变量

1
swap(arr[0], arr[1]);   // O(1)

反转数组

1
reverse(arr.begin(), arr.end());    // O(n)

在 sort 后用,去重,返回去重后数组的结束指针

1
2
3
unique();                           // O(n)
int newLength = unique(arr.begin(), arr.end());
// newLength 为新数组长度

二分查找

1
2
3
4
5
6
7
8
9
10
11
12
bool isExist = binary_search(arr.begin(), arr.end(), value);
binary_search(); //二分查找
//查找对应元素value是否存在 O(logn)

//二分查找
vector<int> arr {1, 2, 2, 3};
int firstLoc = lower_bound(arr.begin(), arr.end(), 2); // 1
int lastLoc = upper_bound(arr.begin(), arr.end(), 2); // 3
//两个函数都是在做一件事
//如果把一个数插入有序数组,它应该插入到哪一个位置
//lower_bound 返回第一插入位置的指针,upper_bound 返回最后一个位置的指针
//O(logn)

next_permutation 与 prev_permutation
用于生成序列的全排列

1
2
3
4
int a[]={1,2,3};
do{
cout << a[0] << " " << a[1] << " " << a[2] << endl;
}while(next_permutation(a, a+3));

若当前调用排列已经达到最大字典序,比如 321,则函数返回 false
可对部分长度全排列

next_permutation 的实现
从最右边开始,两两比较相邻的元素
直至找到右边比左边大的一对,设左边那个为 A
再从最右边开始找比 A 大的第一个元素,设为 B,交换 A 与 B
然后翻转现在 B (之前 A)的位置之后的所有元素
1 3 4 6 5 2 >> 1 3 5 6 4 2 >> 1 3 5 2 4 6

其他

<stack> 栈

1
2
3
4
5
6
7
8
<stack>         //栈:后进先出
stack<int> sta;
sta.push(); //inserts element at the top
int topElement = sta.top(); //accesses the top element
sta.pop(); //removes the top element
sta.empty(); //checks whether the underlying container is empty
sta.size(); //returns the number of elements
//入、出、获取栈顶元素 O(1)

stack 操作包括入、出、获取栈顶元素,复杂度都是 O(1)

栈的典型应用:括号匹配问题

<queue> 队列

1
2
3
4
5
6
7
8
9
<queue>         //队列:先进先出
queue<int> que;
que.push(); //inserts element at the end
int frontElement = que.front(); //access the first element
int backElement = que.back(); //access the last element
que.pop(); //removes the first element
que.empty(); //checks whether the underlying container is empty
que.size(); //returns the number of elements
//入、出、获取队列元素 O(1)

<queue> 包含 queue 和 priority_queue(优先队列)两种数据结构
二者用法和 stack 完全相同

栈和队列都没有 clear 之类的函数,如果想要清空一个栈或者队列,需要循环调用出栈或出队函数

1
2
while(!s.empty()) s.pop();      // 清空栈
while(!q.empty()) q.pop(); // 清空队列
1
2
std::priority_queue             // 优先队列(排队有优先级) O(n)
// 每次取出的是具有最高优先权的元素,即不一定是先进先出

优先队列是一种比较重要的数据结构,它本质上是用堆来实现的
可以以 O(log n) 的效率查找一个队列中的最大值或者最小值
其中是最大值还是最小值是根据创建的优先队列的性质来决定的

1
priority_queue< type, container, function >

这三个参数,后面两个可以省略,第一个不可以
其中:
type:数据类型
container:实现优先队列的底层容器
function:元素之间的比较方式
对于 container ,要求必须是数组形式实现的容器
在 STL 中,默认情况下(不加后面两个参数)是以 vector 为容器
以 operator< 为比较方式,所以在只使用第一个参数时,优先队列默认是一个最大堆(大顶堆)
每次输出的堆顶元素是此时堆中的最大元素

1
2
3
4
5
6
priority_queue<int> que2;
que2.push();
int maxElement = que2.top();
que2.pop();
que2.empty();
que2.size();

如果 type 是一个自己写的结构体,不能够直接比较时
这种情况下就需要我们重载运算符,例如

1
2
3
4
5
6
7
8
struct T
{
int x, y, z;
friend bool operator < (const T &t1, const T &t2)
// bool operator < (const T t2) const
{ return t1.z < t2.z; } // { return z < t2.z; }
}

<set> 集合

<set> 包含 set(集合)、multiset(多重集)

数学上的集合的三个特征:
确定性(任一元素必须是确定属于或不属于某个集合)
互异性(集合中的元素互不相同)
无序性(集合中的元素没有先后之分)

STL 中的 set 的含义就是集合,它是一个有序的容器,里面的元素都是排序好的

1
2
3
4
5
6
7
8
9
10
set<int> st;        // 集合
st.clear(); // set 的清空
st.insert(); // 插入一个元素,自带去重
// 查询有无元素 x
int hav = s.count(x); // 返回 0 或 1
st.find(); // 查找一个元素并返回迭代器
set<int>::iterator it = st.find(x);
st.erase(); // 删除元素
st.size(); // 求集合元素个数
st.empty(); // 判断是否为空集

set 用来保存很多很多元素,并能够在 O(logn) 的时间内查找、删除、添加某个元素,效率非常高

set 最主要的用途:自动去重并按升序排序
set 只能通过迭代器(iterator)访问
迭代器的 ++ 和 – 能够在 O(logn) 的时间里找到第一个比它大(小)的数

set 的遍历

1
2
3
4
5
6
// 注意,set 不支持 it < st.end() 的写法,而 vector 支持
// 原因是 vector 是一维的,在地址上是连续的,而 set 是堆结构,在地址上不连续
// 统一写 it != elem.end() 就好啦
// for (auto it = st.begin(); it != st.end(); it++)
for (set<int>::iterator it = st.begin(); it != st.end(); it++)
printf("%d ", *it);

如果想对 set 中的元素降序排列

1
2
set<int, greater<int> > st;
set<int, greater<int> >::iterator it;

如果 set 中的元素是结构体类型,处理排序问题是应当重载运算符

set 自带去重,而 multiset 允许元素重复,通过 count 可以获得某个元素的数量

1
2
3
4
multiset<int> mst;  //多重集
mst.insert(1);
mst.insert(1);
mst.count(1); // 2

<map> 映射

<map> 包含的第一个数据结构是 pair
要用到两个相关联的变量时,可以偷懒不写 struct

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
pair<int, int> origin;  
//由任意两种类型构成,自带比较函数,先比第一个元素
origin = make_pair(0, 0);
origin.first == origin.second
origin.swap; //返回 swap 的新 pair

pair<string, int> id;
id = make_pair("somebody", 110);

map<string, int> studentHeight;
studentHeight["小明"] = 170;
studentHeight["小红"] = 150;
studentHeight.count("小明"); // 返回 map 中键值等于 k 的元素的个数(1 或 0)
studentHeight.find("小明"); // 存在则返回指向该元素的迭代器,否则返回结束地址 end()
studentHeight.insert(id); // 若插入时键已经存在,则不进行任何操作
studentHeight.erase("小明"); // 删除 map 中键为 k 的元素,返回删除元素的个数(1 或 0)
// 也可以用迭代器 p 当参数,从而删除迭代器 p 所指向的元素
studentHeight.clear(); // 清空 map

<map> 的第二个数据结构是 map
map 是一个键值对(key / value)容器,对于迭代器来说,可以修改 value,而不能修改 key。map 会根据 key 自动排序

可以看成一个超级数组,你可以把字符串或者其他类型当成数组的下标,从而获取其中的值
可以用 { } 初始化
插入、查询、删除操作复杂度都是O(logn)
map 内部使用了 pair ,所以你也可以通过 insert 一个 pair 来插入

map 的遍历

1
2
3
4
5
6
map<int, string> mapSample;
map<int, string>::iterator iter;
for (iter = mapSample.begin(); iter != mapSample.end(); iter++)
{
cout << iter->first << " " << iter->second << endl;
}

<bitset>

bitset 是一个只由0和1构成的数组,其占用空间较小
不仅可以和数组一样用下标访问,还可以进行位运算

1
2
3
4
5
6
7
8
bit<1000> bst;

bst[0] = 1; bst.set(0); //set: sets bits to true or given value
bst[0] = 0; bst.reset(0); //reset: sets bits to false
bst << 1; bst >> 1; bst ^= 1; bst &= 1;
bst.count(); // 1 的个数
bst.to_string();
bst.to_ullong();

其他中的其他

1
2
3
4
5

<functional>
<complex>
<unordered_map>
<unordered_set>

以上头文件都不需要记忆,只要

1
#include <bits/stdc++.h>

就能一键包含所有头文件(Visual Studio 除外)

细节上的一点东西

竞赛细节

  1. 1s 时限运算大约 1e8 次,用复杂度算是否超时
  2. 估计初始化的常数时间
  3. G++ 在输出 double 时不能用 %lf ,要用 %f,不然会WA到哭
  4. 注意多组用例时的EOF、初始化
  5. 数据范围及运算结果均在 1e9 以内时,可令:
1
2
const int INF = 0x3f3f3f3f      //表示无穷大值
memset(arr, INF, sizeof(arr)) //初始化为无穷大

日常练习

版本:VS2019

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <functional>
#include <map>
#include <set>
#include <bitset>
#include <ctime>
#include <cassert>
#include <complex>

const int INF = 0x3f3f3f3f;
const long long INFLL = 0x3f3f3f3f3f3f3f3f;
//#define memset0(x)
//#define memsetN1(x)
//#define memsetINF(x)

using namespace std;

int main()
{
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
int startTime = clock();
#endif


#ifndef ONLINE_JUDGE
printf("Time = %dms\n", clock() - startTime);
#endif
return 0;
}

在线评测系统(Online Judge, OJ)

Virtual Judge