完全二叉树第i个数所在深度:ceil(log2(i+1))
完全二叉树n个数的深度:log2(n+1)+1
取对数头文件math
求幂头文件math
取大数1<<30
100000开根<317
对struct Time中元素t从小到大排序
bool operator<(const Time& t)
{
return e < t.e;
}
方向数组的设置和遍历
dis[4][2]={-1,0,1,0,0,-1,0,1}
for(int i=0;i<4;i++){
int x=last.x+dis[i][0];
int y=last.y+dis[i][1];
}
lower_bound( begin,end,num):左闭右开二分查找第一个>=num的数字,返回该数字的地址,不存在返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):左闭右开二分查找第一个>num的数字,返回该数字的地址,不存在返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
| 按位或 全0才0
& 按位与 全1才1
^ 按位异或 同为0
任何数和 00 做异或运算,结果仍然是原来的数,即 a⊕0=a。
任何数和其自身做异或运算,结果是 00,即 a⊕a=0。
异或运算满足交换律和结合律,即 a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b
memset函数
复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。
声明:void *memset(void *str, int c, size_t n)
全排列next_permutation(algorithm)
int a[3] = {1,2,3};
do
{ cout << a[0] << a[1] << a[2] << endl; }
while (next_permutation(a, a+3));
min_element 返回序列 [first, last)最小元素的位置。
同理 max_element。
asc2:a97-z122
sort algorithm头文件,左开右闭 自定义
bool cmp0(int x, int y){ return x > y;}//从大到小
bool cmp1(int x, int y){ return x < y;}//从小到大
并查集:找根节点+连通
const int N=1005 //指定并查集所能包含元素的个数(由题意决定)
int pre[N]; //存储每个结点的前驱结点
int rank[N]; //树的高度
void init(int n) //初始化函数,对录入的 n个结点进行初始化
{
for(int i = 0; i < n; i++){
pre[i] = i; //每个结点的上级都是自己
rank[i] = 1; //每个结点构成的树的高度为 1
}
}
int find(int x) //查找结点 x的根结点
{
if(pre[x] == x) return x; //递归出口:x的上级为 x本身,则 x为根结点
return find(pre[x]); //递归查找
}
int find(int x) //改进查找算法:完成路径压缩,将 x的上级直接变为根结点,那么树的高度就会大大降低
{
if(pre[x] == x) return x; //递归出口:x的上级为 x本身,即 x为根结点
return pre[x] = find(pre[x]); //此代码相当于先找到根结点 rootx,然后 pre[x]=rootx
}
bool isSame(int x, int y) //判断两个结点是否连通
{
return find(x) == find(y); //判断两个结点的根结点(即代表元)是否相同
}
bool join(int x,int y)
{
x = find(x); //寻找 x的代表元
y = find(y); //寻找 y的代表元
if(x == y) return false; //如果 x和 y的代表元一致,说明他们共属同一集合,则不需要合并,返回 false,表示合并失败;否则,执行下面的逻辑
if(rank[x] > rank[y]) pre[y]=x; //如果 x的高度大于 y,则令 y的上级为 x
else //否则
{
if(rank[x]==rank[y]) rank[y]++; //如果 x的高度和 y的高度相同,则令 y的高度加1
pre[x]=y; //让 x的上级为 y
}
return true; //返回 true,表示合并成功
}
最小生成树
prim将任意节点作为根,再找出与之相邻的所有边(用一遍循环即可),再将新节点更新并以此节点作为根继续搜,维护一个数组:dis,作用为已用点到未用点的最短距离。
kruskal先把边按照权值进行排序,用贪心的思想优先选取权值较小的边,并依次连接,若出现环则跳过此边(用并查集来判断是否存在环)继续搜,直到已经使用的边的数量比总点数少一即可。
pair utility头文件
pair name_age("Tom", 18);
pair name_age2(name_age); // 拷贝构造初始化
//pair类型的使用相当的繁琐,如果定义多个相同的pair类型对象,可以使用typedef简化声明:
typedef pair Author;
Author proust("March","Proust");
Author Joy("James","Joy");
最短路径
Dijkstra算法:一个一个加点
//最短路径模板 dijstra算法
for (int i = 1; i <= 2021; i++)
{
ll u = -1, minn = inf;
for (int j = 1; j <= 2021; j++)//找到起点
{
if (!vis[j] && dis[j] < minn)
{
minn = dis[j];
u = j;
}
}
if (u == -1)
break;
vis[u] = 1;
for (int v = 1; v <= 2021; v++)
{
if (!vis[v])
dis[v] = min(dis[v], e[u][v] + dis[u]);
}
}
0-1背包:dp+压缩数组
for (int i = 1; i <= m; i++)//取前i个
{
for (int j = t; j >= w[i].p; j -- )//t是容量
{
dp[j] = max(dp[j], dp[j - w[i]. p] + w[i].q);
//根据价值大小选择要第i个或不要i
}
}
cout << dp[t] << endl;
文件操作函数
//向文件写五次hello。
//c_str()
fstream out;
out.open("C:\\Users\\asusa\\Desktop\\蓝桥\\wr.txt", ios::out);
string s = "hello";
for (int i = 0; i < 5; ++i)
{
out << s.c_str() << endl;
}
out.close();
//如果想要以追加方式写,只需要open函数的第二个参数改为app
out.open("C:\\Users\\asusa\\Desktop\\蓝桥\\wr.txt", ios::app);
//按行读取
string filename = "C:\\Users\\asusa\\Desktop\\蓝桥\\rd.txt";
fstream fin;
fin.open(filename.c_str(), ios::in);
vector v;
string tmp;
while (getline(fin, tmp))
{
v.push_back(tmp);
}
for (auto x : v)
cout << x << endl;
//按单词读取只需要把while循环条件改一下
while (fin >> tmp)
{
v.push_back(tmp);
}
fopen打开文件;fclose(文件指针)
文件指针名=fopen(文件名,使用文件方式)
例如:
FILE *fp;fp=("file a","r");//在当前目录下打开文件file a, “读”操作,fp指向该文件。
FILE *fphzk; fphzk=("c:\\hzk16',"rb");//打开C盘下的文件hzk16, 按二进制方式进行读操作。两个反斜线“\ ”第一个表示转义字符,第二个表示根目录
使用文件方式:头文件stdio.h
r(read): 读,有r必须保证文件存在
w(write): 写,文件不存在则自动建立
a(append): 追加写
t(text): 文本文件,可省略不写
b(banary): 二进制文件
+: 读和写
文件读写的函数:
·字符读写函数 :fgetc和fputc
FILE *fp;
char ch;
ch=fgetc(fp);
while (ch != EOF)
{
putchar(ch);
ch=fgetc(fp);
}
·字符串读写函数:fgets和fputs
fgets(字符数组名,n,文件指针);
其中的n是一个正整数表示从文件中读出的字符串不超过 n-1个字符。在读入的最后一个字符后加上串结束标志' '。例如:fgets(str,n,fp);的意义是从fp所指的文件中读出n-1个字符送入字符数组str中。
如遇到了换行符或EOF,则读出结束
·数据块读写函数:freed和fwrite
fread(buffer,size,count,fp);
其中buffer是一个指针表示存放输入数据的首地址。 size 表示数据块的字节数。count 表示要读写的数据块块数。fp 表示文件指针。
例如:
fread(fa,4,5,fp); 其意义是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续读5次,即读5个实数到fa中。
·格式化读写函数:fscanf和fprinf
fscanf(文件指针,格式字符串,输入表列);
fprintf(文件指针,格式字符串,输出表列);
例如:
fscanf(fp,"%d%s",&i,s);
fprintf(fp,"%d%c",j,ch);
rewind(文件指针); 它的功能是把文件内部的位置指针移到文件首。
fseek(文件指针,位移量,起始点); “文件指针”指向被移动的文件。 “位移量”表示移动的字节数,要求位移量是long型数据,以便在文件长度大于64KB 时不会出错。当用常量表示位移量时,要求加后缀“L”。“起始点”表示从何处开始计算位移量,规定的起始点有三种:文件首0,当前位置1和文件尾2。
容器
//vector
size();//返回容器中元素的个数
empty();//判断容器是否为空
front();//返回容器中第一个数据元素
back();//返回容器中最后一个数据元素
insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele.
push_back(ele); //尾部插入元素ele
pop_back();//删除最后一个元素
erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素
erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素
//deque
deque.size();//返回容器中元素的个数
deque.empty();//判断容器是否为空
push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器第一个数据
//stack
push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素
empty();//判断堆栈是否为空
size();//返回堆栈的大小
//queue
push(elem);//往队尾添加元素
pop();//从队头移除第一个元素
back();//返回最后一个元素
front();//返回第一个元素
//lise双向循环链表
push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
front();//返回第一个元素。
back();//返回最后一个元素。
reverse();//反转链表,比如lst包含1,3,5元素,运行此方法后,lst就包含5,3,1元素。
sort(); //list排序
//set&multiset(multi允许重复值)
set st;//set默认构造函数:
mulitset mst; //multiset默认构造函数:
find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
count(key);//查找键key的元素个数
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
//pair
//第一种方法创建一个对组
pair pair1(string("name"), 20);
cout << pair1.first << endl; //访问pair第一个值
cout << pair1.second << endl;//访问pair第二个值
//第二种
pair pair2 = make_pair("name", 30);
cout << pair2.first << endl;
cout << pair2.second << endl;
//pair=赋值
pair pair3 = pair2;
cout << pair3.first << endl;
cout << pair3.second << endl;
//map pair的set
map mapTT;//map默认构造函数:
mapStu.insert(pair(3, "小张"));
find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回map.end();
count(keyElem);//返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。