笔记 | 蓝桥复习的一些细节汇总

bug 细节 知识点

完全二叉树第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元素的迭代器。

你可能感兴趣的:(算法,蓝桥杯)