1.vector尽可能不要v.resize(n),可以尝试在刚开始的时候就直接 vector<int> v(N)这样不会导致运行错误
2.while循环的条件不稳定性 比如kmp 和 快排的板子,都是需要在while循环里面加上重复的条件的,就是因为虽然是满足条件了才能进入循环,但是也可能在没有出去进行下一次判断的时候就出现条件不满足的时候了
3.递推 或者是一个变量可能是 “+=”的时候要注意的是 开一个long long来存储变量,这个可能在题目的数据范围看不出来,但是要记得开long long
4.如果说涉及到i - 1,这样的下标,强烈建议下标从1开始,可以少一点预处理判断
5.活动 - AcWing我现在感觉万物皆可dp,这个题目你能想到是dp?求最少操作次数:其实说万皆可dp是非常的有道理的,因为这个东西
60x3f3f3f3f这个东西可以用来表示无穷大,真的无穷大,数组的化就是memset(0x3f)
6.&v = x;
v是变量x的一个别名,两者具有相同的地址空间
7按照从左到右,从上到下的顺序的点的顺序转化成坐标的程序:
#include<iostream>
using namespace std;
int main(){
int n;cin >> n;
cout << (n - 1) / 4 + 1 << " " << (n - 1) % 4 + 1;
return 0;
}
8.0一道题目先思考的应该是如果数据范围很小答案是什么,能不能想办法枚举所有的答案,能不能按照题目的描述来一步步模拟着做题目
9.0关于string 和 char
#include <iostream>
using namespace std;
int main(){
char ch = 'c';
string s = ch;
}
//这个程序是错误,不相同的数据类型 没有办法直接相等
//所以我们可以采用这种写法:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
int test_cases;
cin >> test_cases;
for (int test_case = 0; test_case < test_cases; test_case++) {
vector<string> v(3);
for (int i = 0; i < 3; i++)
cin >> v[i];
string ans = "DRAW";
for(int i = 0; i < 3; i++) {
if (v[i][0] == v[i][1] && v[i][1] == v[i][2] && v[i][0] != '.')
ans=v[i][0];
}
for (int i = 0; i < 3; i++) {
if (v[0][i] == v[1][i] && v[1][i] == v[2][i] && v[0][i] != '.')
ans=v[0][i];
}
if (v[0][0] == v[1][1] && v[1][1] == v[2][2] && v[0][0] != '.')
ans=v[0][0];
if (v[0][2] == v[1][1] && v[1][1] == v[2][0] && v[0][2] != '.')
ans=v[0][2];
cout << ans << endl;
}
return 0;
}
这样非常有利于 string 和 char数据类型的转换 也非常有利于字符串的读入
10.0我最大的收获就是熟练掌握了「从特殊到一般」的技巧。大多数题目是不能一眼看出规律的,这就需要从小数据或特殊数据出发(比如元素值只有 0 和 1),去研究并发现性质和规律。在做构造题时,应当重点摸索和体会这一技巧。
11.0程序美就美在可以自定义实现出来我们想要的东西:比如说:实现pair当中第一个关键字按照从大到小,第二关键字从小到大来进行排序,我们是可以自己实现的
bool cmp(const pair<int, char> a, const pair<int, char> b) {
return a.first > b.first;//自定义的比较函数
if(a.first == b.first) return a.second < b.second;
}
sort(v.begin(),v.end(),cmp);
如果是结构体的话需要如果我们需要按照结构体中的某一个元素进行排序,我们需要这样写(这样就是按照r从小到大排序)
struct Range
{
int l, r;
bool operator< (const Range &W)const
{
return r < W.r;
}
}
12.0关于赋初值,有两个东西fill 和 memset,如果是0 -1 INF我们尽量选择使用memset,其他的都使用fill(这个是可以对vector来进行使用的)
13.0max_element
是一个算法函数,它用于查找给定范围内的最大元素,并返回指向该最大元素的迭代器 所以*max_element
的作用就是来表示最大值时谁的
14.0 while(scanf(“%d%d“)!=EOF):在我们进行包括scanf等的输入函数使用时,其实用户在cmd中的输入实际是存放于缓冲区当中,当用户键入回车那一瞬间,之前输入的数据才会被存进去,而这里无论是单个字符还是字符串,我们都知道scanf的返回值呢是表示成功接受到的对象的个数,那这里如果遇到特殊情况,比如缓冲区文件流满等问题,那么scanf将如何处理呢?答案是返回-1 ! 这里不光是scanf,返回值为个数的函数,遇到文件流满大多都会返回-1,所以这个-1用的比较多,那么stdio.h就索性专门定义一个宏来表示,取End Of File(文件末尾的意思)的前三个字母即组成EOF,所以也就有了 #define EOF (-1) 这样的话!
15.0char 类型也是可以异或的,ch ;ch ^= 1;这样如果ch是0就是变成1,如果ch是1就会变成0
16.0以后 *= 或者说 +=,咱们就记住,尽可能不要使用,莫名其妙小错误
17 可以使用isdigist()来判断一个字符是不是数字字符
18.0写代码 的顺序一定是先考虑全局,然后在考虑局部,而不是上来就考虑特殊情况,这样的思考顺序是有很大的问题的,我们一定是先考虑全局有什么规律,再看看局部需不需要调整一下
19用普通数组来统计字母出现的次数:
int count[26] = {0}; // 初始化每个元素为0
for (int i = 0; i < str.length(); i++) {
char ch = str[i];
// 判断是否为小写字母
if (ch >= 'a' && ch <= 'z') {
// 将字母转换为在数组中的索引
int index = ch - 'a';
// 增加对应字母的计数器
count[index]++;
}
}
for (int i = 0; i < 26; i++) {
// 将索引转换为对应的字母
char ch = 'a' + i;
// 输出字母和对应的次数
cout << ch << ": " << count[i] << endl;
}
20 int:-2,147,483,648 (−2^31) 到 2,147,483,647 (2^31−1)
long long :-2^63 到 2^63-1
usigned long long :0 到 2^64-1,它的取值范围是从 0 到 2^64-1,即最大可以表示的整数值为 (2^64 - 1)。因此,在进行模运算时,如果使用 unsigned long long
表示数值,相当于对结果进行了模 2^64 的操作。
21输出单个yes或者no用puts()也是一个好的选择,有回车
22闰年判断方法:能被400整除或者能被4整除但是不能被100整除的
23__builtin_popcount(x)算一个数字当中二进制1的个数
24:priority_queue< int> 实际上等价于 priority_queue<int, vector, less< int>>
priority_queue<int, vector<int>, greater<int>>s;这个是小根堆