C++编程记忆3.0

C++编程记忆 3.0

0.

#include <bits/stdc++.h>
一个包含所有c/c++的头文件的头文件
gcc -mavx2 -S -fverbose-asm fun.c #看详细的汇编语言结果
#pragma GCC optimize (“O3”)
#pragma GCC target (“sse4”)
#pragma GCC optimize(“unroll-loops”)

  • gdb调试
    1. gcc -g test.c -o o.out; gdb o.out
    2. 显示当前的代码: l
    3. 在某一行打断点: b 行号
    4. 查看断点信息: info b
    5. 根据编号删除断点: delete 7
    6. 根据行号删除断点: clear 7
    7. 开始运行程序: r (run)
    8. 让程序继续运行: c (continue)
    9. 执行单条语句: n (next)
    10. 逐步执行: s (step)
    11. 重复上条命令: 按回车
    12. 查看某个变量: p (print) 变量名
    13. 查看变量类型: whatis 变量名
    14. 查看函数堆栈: bt
    15. 结束调试: finish
    16. 退出调试: q

运算符优先级

CMakeList.txt

1.scanf && cin

  • %lld 对应long型变量 %d 对应 int

  • %lf 对应double型变量

  • 过滤空格: c i n > > w s ; cin>>ws; cin>>ws;

  • 获取输入字符

     char c;
     getchar();  // 如果字符前有一个回车或一个空格就用getchar去掉,或者在前面加\n
     scanf("%c",&c);
     while((c=cin.get())!=EOF) map[c]++;
    
  • 获取输入字符串

     // 方法一: 在PAT上没这个函数,在VS里可以
     char str[100];
     gets_s(str);// 可以读取空格,回车结束;gets没有了
     int N=strlen(str);
     
     // 方法二
     int num=0;
     char ans[90][90];
     while(scanf("%s",ans[num])!=EOF){num++;}// EOF为-1,num是单词个数
     
     //方法三
     #include<stack>
     stack<string> v;
     string s;
     while(cin>>s)v.push(s);
     cout<<v.pop();
     
     // 方法四
     string name;
     getline(cin,name); // 可读取空格
     
     // 方法五:scanf读入string, 本方法不建议使用,可能会输出多余空格
     string a; a.resize(20);
     scanf("%s",&a[0]);
     
     // 方法六
     char s1[10000];
     cin.getline(s1,100,'\n');
     
     // 方法七
     string name;
     getline(cin,name);
    
  • 循环获取输入,可直接while(cin>>a>>b){}

  • 忽略输入字符

     scanf("%d%*c%d",&a,&b); //输入1n3,a=1,b=3,中间是字符不能是数字,可以是回车空格
    
  • sscanf

     char a[50];
     scanf("%s",a);
     double temp;
     sscanf(a,"lf",&temp); //  读出a中的double到temp
     sprintf(b,"%.2f",temp); //  将temp转化为二位小数的字符b
     
     // 连接功能
     char str[20];
     int a=20984,b=98235;
     ssprintf(str,"%3d%6d",a,b);// 3表示a在str中至少占3位,右对齐,6表示至少占6位
    
  • 忽略回车

     // 一次只能忽略一个
     #include <numeric>
     #include <limits>
     cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    

2. printf && cout

  • 0xf表示16,长整数 int64_t

  • %02d 输出2位整数,不足则以0填充,%010d, 输出10位整数不足则以0填充

  • %.10f 输出10位float 或double型小数

  • %s 输出一个char一维数组

     //printf输出string
     string str;cin>>str;
     printf("%s",str.c_str());
    
  • cout填充与精度

    int n=10;char a ='b';
    cout<<setw(n)<<setfill(a)<<a;
    
    int a=100; cout<<fixed<<setprecision(1)<<double(a); // 输出一位小数
    cout<<setiosflags(ios::fixed)<<setprecision(2)<<res;
    
  • char a[11]; cin >> a; puts(a); // 即cout<<a;

  • 另一种输出

     #include<iterator>
     int A[] = { 1,4,3,7,10 };
     const int N = sizeof(A) / sizeof(int);
     vector<int> vec(A, A + N);
     ostream_iterator<int> output(cout, " ");
     cout << "Vector vec contains:";
     copy(vec.begin(), vec.end(), output);
    
    std::copy(std::begin (data), std::end(data), std::ostream_iterator<int> {std::cout, " "});
    

3. string

  • 数字转字符串:to_string

    #include <sstream>
    int a=1; string s=to_string(a);
    cout << "0" + to_string(60);
    
  • find

    #include <cctype>
    string s1, s2;
    cin >> s1 >> s2;
    if(s2.find(s1[0]) == string::npos);//find的第二个参数可以是一个整数表示位置
    
  • rbegin

    string n; cin>>n;//从后面遍历到前面
    for(auto it=n.rbegin();it!=n.rend();it++)
        cout<<*it;
    //  string也有begin和end
    

4. fill

  • 二维数组填充

    int e[501][501];
    fill(e[0],e[0]+501*501, 123);
    
  • 一维数组填充

    int dis[501]; fill(dis,dis+501,456);
    
  • setfill()后面一定还要输出一个数据哪怕是一个空字符串!

    int n=10;char a ='b';
    cout<<setw(n)<<setfill(a)<<a;
    
  • 字符串填充

    string a,b;cin>>a>>b;
    int lena=a.length(),lenb=b.length();
    if(lena>lenb) b.append(lena-lenb,'0'); // 往b的末尾补0直到与a等长
    else a.append(lenb-lena,'0');
    

5. memcpy && copy&&sizeof

  • 复制数组a给b

    #include<string>
    memcpy(b,a,sizeof(int)*n);
    
    vector<int> a(5,0),b(5,0);
    copy(a.begin(),a.end(),b.begin());
    
    int a[100][10];
    int *b = new int[1000];
    int c; cin >> c;//1000
    int d[c];
    int *e = (int *)malloc(sizeof(int) * 1000);
    cout << sizeof(a)<<" "<<sizeof(b)<<" "<<sizeof(d)<<" "<<sizeof(e)<< endl;
    //        4000            4              4000             4
    

6. struct

  • 定义结构体时用了 typedef 的话,结构体定义完后的右括号后面声明的数组不可以用,去掉typedef就可以用那个结构数组了

7. vector + map

  • 赋值

    vector<int> o;
    o.push_back(123);
    cout<<o[0];
    cout<<o.size();
    o.resize(8,100); // 将第2至第8个元素赋值为100
    
    vector<int> a(5,2); //  长度5,值为2
    
    int in[100]={0};
    vector<int> tin(in,in+10); // 把数组in前10个数push到tin里
    
    ans.assign(res.begin(),res.end());// 都是 vector<int>类型
    
  • 去重

    // 法1
    vector<char> con;
    sort(con.begin(), con.end());
    con.erase(unique(con.begin(), con.end()), con.end()); // 删除重复元素
    con.erase(con.begin()); //  删除第一个元素
    
    // 法2 在插入时检测
    if (count(con.begin(), con.end(), a[i]) == 0)  // 如果不存在
    	con.push_back(a[i++]);
    
  • 遍历 A16

    map<string,vector<node>> custom;
    string str;cin>>str;
    vector<node> data(n); 
    //此处省略初始化data[0]
    custom[str].push_back(data[0]);
    
    // 方法1
    for(auto it:custom)
    {
        vector<node> temp=it.second;
        cout<<it.first;
    }
    // 方法二
    map<string, vector<node>>::iterator it;
    for(it=custom.begin();it!=custom.end();it++)
    		 if(it->second==data[0]) cout << it->first <<"  ";
    //注: map用char*做映射和string做映射不同,用char*时每赋值一次就会多一个这样的同名映射而不会合并  见A95
    
    // 方法3
    unordered_map<string, int> mp;
    for (auto [s, i] : mp)
    unordered_map<int, int> cnt;
    for (auto &[_, m] : cnt)
    
  • 二维

    vector<vector<int>> school(m);
    vector<int> school[m];
    vector<<vector<int>> a( m, vector<int>(n));
    
  • 查找

    map<string, int> wordmap; string word="123";
    if(wordmap.find(word) != wordmap.end())
    	          wordmap[word]++;
    
    std::find(wordmap.begin(), wordmap.end(), "China")==wordmap.end();
    
    wordmap.count("123");
    
  • 取最后值

    vector<int> path;
    _for(0, 10) path.push_back(i);
    cout << *(path.end()-1);
    
  • 取前k个值(leetcode973)

    vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
    return {points.begin(), points.begin() + k};}
    
  • 插入

    vector<int> v;
    v.push_bavk(123); v.push_back(456);
    v.insert(v.begin()+1,9);// 从第一个元素后插入9, string也可这样插入,第二个参数是字符
    
  • 删除

    vec.erase(remove(vec.begin(), vec.end(), 3), vec.end());//删除值为3的元素
    
    typedef pair<int, int> Point;
    map<Point, int> cnt;
    cnt.erase({x, y});
    
  • 查找

    map<int, int> intervals;
    // 如果不存在这样的区间,interval1 为尾迭代器
    auto interval1 = intervals.upper_bound(val); // 最小的且满足 l1 > val 的区间 interval1 = [l1, r1]
    // 最大的且满足 l0 <= val 的区间 interval0 = [l0, r0]
    auto interval0 = (interval1 == intervals.begin() ? intervals.end() : prev(interval1)); 
    // interval0->first 获取key
    intervals.erase(interval0);
    intervals.emplace(left, right);
    

8. memset

  • int c[10]; memset(c,0,40); // 只赋0和-1、1
  • 在库文件cstring和string.h里

9. isxxx

  • isdigit(a[i]) // a[i]是不是数字字符
  • isalpha(c[j]) // c[j]是不是英文字母
  • isupper(b[k])

10. 转换&& substr && stoi &&stof&& atoi &&atof&& toupper

  • 获取子字符串并转数字(1)

    #include <iomanip> // PAT
    #include<sstream> // VS
    stringstream ss;
    ss<<s.substr(5);  // 取子字符串s[5]至s的结尾到容器ss中,
    int evalue;
    ss>>evalue; //转成数字
    
  • 获取子字符串并转数字(2)

    string s; cin>>s;
    string t = s.substr(4,3); //获取子字符串s[4]开始长为3的字符串
    int n = stoi(s.substr(2));// 将s[2]至s的结尾的子字符串转化为数字,可含符号
    float a= stof(s);
    double b= atof(s.c_str());
    
  • 大小写转换

    char a; cin >> a;
    cout << (char)toupper(a);
    string get;cin>>get;
    transform(get.begin(), get.end(), get.begin(), ::tolower);
    
    for (char& ch: s) 
    	  if (ch >= 65 && ch <= 90) 
          ch |= 32; // 大写转小写
    
  • atoi() 将char数组转成int

  • sscanf(argv[1], “%lld”, &n);

  • 构造

    n = strtoll(argv[1], NULL, 10);//10进制
    n = strtold(argv[1], NULL);
    int l = strlen(argv[1]) - 1;  // 输入的0的个数
    int l2 = sizeof(argv[1]) - 1; // 每次都是7
    cout << l << "  " << l2 << endl;
    cout << argv[2] << endl;
    n = 1;
    while (l--)
      n *= 10;
    
  • 将int转char数组

    int x;  cin>>x;
    char s[100];
    snprintf(s, sizeof(s), "%0100d", x);
    itoa(x,s,10);  //  第三个参数是进制,可能有的不支持
    cout<<x;
    
  • long long d = 1LL * nums[i] - nums[j]

  • char转string:string s = “123”; string a = string(1, s[1]); s.push_back(s[0]);

11. reverse

  • 反转字符串

    string s;cin>>s;
    reverse(s.begin(),s.end());
    
  • 传vector

    vector<int> a(5); a[0]=1;a[1]=2;a[2]=3;a[3]=4;a[4]=5;
    reverse(begin(a)+2,begin(a)+5); // 不包括右边
    

12. sort

  • 快速排序

    bool cmp(int a,int b) {return b>a;} // 降序
    vector<int> v;
    for(int i=0;i<100;i++)v.push_back(rand());
    sort(v.begin(),v.end(),cmp);
    for(int i=0;i<100;i++) cout<<v[i]<<" ";
    
  • 降序

    sort(a, a+n, greater<int>()); // less<int>()
    sort(nums.begin(), nums.end(), greater<>()); // vector<int> &nums
    
  • 简写

    sort(p, p + n, 
         [](const project& p1, const project& p2) {return p1.d < p2.d; });
    
    // 按值传递r0、c0,也可以用&r0
    sort(ret.begin(), ret.end(), [r0,c0](vector<int>& a, vector<int>& b) {
         return abs(a[0] - r0) + abs(a[1] - c0) < abs(b[0] - r0) + abs(b[1] - c0);});
    
    sort(nums.begin(), nums.end(), [](const int &x, const int &y) {
                long sx = 10, sy = 10;
                while (sx <= x) 
                    sx *= 10;
                while (sy <= y) 
                    sy *= 10; 
                return sy * x + y > sx * y + x;
            });
    
    // vector<string> dic 按长度降序、按字典序升序排列
    sort(dic.**r**begin(), dic.**r**end(), [](auto&& a, auto&& b){
        return a.size() < b.size() || a.size() == b.size() && a > b;});
    
  • 稳定排序

    // vector<string> words;
    stable_sort(begin(words), end(words), [](auto&& a, auto&& b){return a.size() < b.size();});
    

13. strcmp

  • int strcmp(const char* s1, const char* b); // s1<s2时返回负数,相等时返回0

    char a[10],c[4]="123";
    //三个a都会输出
    if(strcmp(a,c)==0) cout<<a;
    if(strcmp(a,"123")==0)cout<<a; 
    if(strcmp(a,"123\0")==0)cout<<a; 
    

14. round

  • 四舍五入

    int a,b,c;cin>>a>>b>>c;
    a=round((a+b+c)/3.0)+0.5;
    

15. 二分查找

  • 从小到大排序,第一个大于b的数的下标

    int j=upper_bound(a,a+n,b)-a;// j-1 就是第一个小于等于b的数的下标
    
  • 从大到小排序,第一个小于b的数的下标

    int it_i = upper_bound(a.begin(), a.end(), b, greater<int>())-a.begin();
    //再减一就是最后一个大于等于b的数的下标
    
  • 从小到大排序,第一个大于等于b的数的下标

    int k=lower_bound(a.begin(), a.end(),b)-a.begin(); // 从小到大排序,第一个大于等于b的数的下标
    set<int> available;
    auto p = available.lower_bound(b); // 大于等于b的最小数
    
  • 从大到小排序,第一个小于等于b的数的下标

    int it_j = lower_bound(a.begin(), a.end(), b, greater<int>())-a.begin();
    //再减一就是最后一个大于b的数的下标
    

16. freopen

  • 打开文件

    freopen("file.in","r",stdin);
    freopen("file.out","w",stdout);
    

17. set

  • 插入

    #include<set>
    set<int> s;
    s.insert(123);
    
  • 删除

    set<node> s;
    auto it = s.find(node{num, book[num]});
    if (it != s.end()) s.erase(it);
    
    s.erase(s.begin()); // 删除最小值
    // 最小值 *s.begin()  最大值 *s.rbegin()
    
  • 用于加快查找

    vector<string> wordList;  string t="123";
    unordered_set<string> wordSet(wordList.begin(),wordList.end());
    //if(std::find(wordList.begin(),wordList.end(),t)!=wordList.end()){...}
    if(wordSet.count(t)){...}
    
  • 找倒数第二个数

    set<int> st;
    cout<<*prev(prev(st.end()));
    
  • 遍历

    set<char>::iterator iter = temp.begin();
    while (iter!=temp.end())
    {
    	cout<<*iter;
    	iter++;
    }
    
  • 插入+查找

    unordered_set<long> seen;
    if (seen.insert(next).second) // 如果之前没有插入过
        heap.push(next);
    

18. 运算符重载

struct node {
	int value; int cnt;
	bool operator < (const node & a) const{
		return cnt != a.cnt ? cnt > a.cnt:value < a.value;
	}
};
set<node> s; // s插入时会自动调用<排序

struct plural {
	int a, b;

	plural() { a = 0, b = 0; }

	plural(int A, int B) : a(A), b(B) {}

	friend istream &operator>>(istream &in, plural &p) {
		in >> p.a >> p.b;
		return in;
	}

	friend ostream &operator<<(ostream &out, plural &p) {
		out << p.a;
		if (p.b > 0)out << "+";
		out << p.b << "i";
		return out;
	}

	friend plural operator+(const plural &A, const plural &B) {
		plural p(A.a + B.a, A.b + B.b);
		return p;
	}

	friend void operator+=(plural &A, const plural &B) {
		A.a += B.a;
		A.b += B.b;
	}

	friend plural operator*(const plural &A, const plural &B) {
		plural p(A.a * B.a - A.b * B.b, A.a * B.b + A.b * B.a);
		return p;
	}

	friend void operator*=(plural &A, const plural &B) {
		plural p(A.a * B.a - A.b * B.b, A.a * B.b + A.b * B.a);
		A = p;
	}
};

19. auto it

// 用箭头
for(auto it = s.begin();it != s.end(); it++)
	printf(" %d", it->value);

// 用小数点
for (auto it : s) 
	cout << " " << it.value;

// 值拷贝
vector<vector<int>> matrix;
auto matrix_new = matrix;
maxtrix = matrix_new;

20. pair

#include<utility>
pair<string, int> name_age("Tom", 18);
name_age.first="Sam";
name_age=make_pair("Bob",19);

21. 优先级队列

priority_queue<**tuple**<double, int, int>> q;

priority_queue<pair<int, int>> q;// 大根堆,python是小根堆
q.emplace(197, 0); // 按第一个值建堆,第二个值表示197在原来的数组中的索引
cout<<q.top().first; // 堆顶元素的值最大

auto cmp = [&](const char& letter1, const char& letter2) {
    return counts[letter1 - 'a']  < counts[letter2 - 'a'];
};
// 按cmp排序建大根堆,第二个元素存堆,必须用vector
priority_queue<char, vector<char>,  decltype(cmp)> queue{cmp}; // {}用()也行
queue.push('a');
priority_queue<int, vector<int>, less<int>> queMin;// 大根堆

priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq; //  小根堆
pq.emplace(0, k - 1);
auto p = pq.top();
pq.pop();

// 小根堆
vector<pair<int, int>> power;
priority_queue q(greater<pair<int, int>>(), move(power));

22. char*处理

  • strcpy

    char* date=new char[9];
    const char* month;
    mon="November";  
    strcpy(date,month);  // const char* 转char*
    

23. max_element&&accumulate

unordered_map<char, int> freq;
int maxExec = max_element(freq.begin(), freq.end(), [](const auto& u, const auto& v) {return u.second < v.second;})->second;
#include <numeric>
int maxCount = accumulate(freq.begin(), freq.end(), 0, [=](int acc, const auto& u) {return acc + (u.second == maxExec);});  //  maxExec出现次数
long long sum = accumulate(res[0].begin(), res[0].end(), 0ll); // 对二维vector的第0行求和

24. 单调队列

deque<int> opt = {0,0};
int f = opt.front();
int b = opt.back();
opt.push_back(1);
opt.pop_front();
opt.pop_back();

25. tie (c++17)

// 无需显示定义中间变量 | 矩阵翻转的例子
tie(matrix[i][j], matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1]) \
= make_tuple(matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1], matrix[i][j]);

26. iota

#include<numeric>
int numbers[10]; // 也可以是vector
std::iota (numbers,numbers+10,100); // 从100开始赋值,累加到109

vector<int> ans(n);
iota(ans.begin(), ans.end(), 0);

27. 简写实现函数

vector<vector<int>> points;
auto dist = [&](int x, int y) -> int {
return abs(points[x][0] - points[y][0]) + abs(points[x][1] - points[y][1]);};

// 递归实现函数内部函数,返回值是void,输入两个int
function<**void(int, int)**> backtrack = [&](int pos, int mask) {
  if (pos == masks.size()) {
      ans = max(ans, __builtin_popcount(mask)); // 求1的个数
      return;
  }
  if ((mask & masks[pos]) == 0) { // mask 和 masks[pos] 无公共元素
      backtrack(pos + 1, mask | masks[pos]);
  }
  backtrack(pos + 1, mask);
};

// 检查是否是元音字符 isVowel('a')
auto isVowel = [vowels = "aeiouAEIOU"s](char ch) {
    return vowels.find(ch) != string::npos;
};

function<int(int)> f = [&](int x){
	  if(x==1) return 2;
	  else if(x==2) return 4;
  	else return f(x-1)+f(x-2);
};

28. 红黑树(求最大值最小值)

multiset<int> s;
s.insert(1);   // 相同时是插在右边
int maxs=*s.rbegin();
int mins=*s.begin();
s.erase(s.find(1));

29. any_of

unordered_map<int, int> freq;
if (any_of(freq.begin(), freq.end(), [](const auto& entry) {return entry.second != 0;}))    return false;

30. __builtin_popcount

return __builtin_popcount(x ^ y);// x和y的二进制中不同位的个数

31. array 二维数组

static constexpr array<array<int, 6>, 2> dist = {{
        {0, 1, 2, 1, 2, 3},
        {3, 2, 1, 2, 1, 0}
}}; // 括号不能省

array<int, 26> cnt{};

32. 自定义map

// map: array<int, 26> 转 int 转 vector<string>
// 自定义对 array<int, 26> 类型的哈希函数
auto arrayHash = [fn = hash<int>{}] (const array<int, 26>& arr) -> size_t {
     return accumulate(arr.begin(), arr.end(), 0u, [&](size_t acc, int num) {
                return (acc << 1) ^ fn(num);
     });
};
unordered_map<array<int,26>,vector<string>,decltype(arrayHash)> mp(0, arrayHash);
array<int, 26> counts{};
for (int i = 0; i < str.length(); ++i) 
    counts[str[i] - 'a'] ++;
mp[counts].emplace_back(str);

33. 高效位运算

// 在函数名后面加上l或ll代表传入unsigned long/unsigned long long

// 求mask中从右数第一个1右边0的个数
int i=__builtin_ctz(mask);

// 求mask中从左数第一个1左边0的个数
int i=__builtin_clz(mask);

// 最后一位1是从右数第几位
int i=__builtin_ffs(mask);

// 二进制中1的个数
int i=__builtin_popcount(mask);

// 奇偶校验位,mask的1的个数模2的结果
int i=__builtin_parity(mask);

__builtin_clz(num) // 前导0的个数
// 实现
int zeros(unsinged int num) {
    unsinged int clz = 0;
    if ((num >> 16) == 0) {
        clz += 16;
        num <<= 16;
    }
    if ((num >> 24) == 0) {
        clz += 8;
        num <<= 8;
    }
    if ((num >> 28) == 0) {
        clz += 4;
        num <<= 4;
    }
    if ((num >> 30) == 0) {
        clz += 2;
        num <<= 2;
    }
    if ((num >> 31) == 0) {
        clz += 1;
    }
    return clz;
}
__builtin_popcount(num) // 二进制中1的个数
int count(int num) {
    num = (num & 0x55555555) + ((num >> 1) & 0x55555555); // 相邻两位上的1的和存在这两位上
    num = (num & 0x33333333) + ((num >> 2) & 0x33333333); 
    num = (num & 0x0F0F0F0F) + ((num >> 4) & 0x0F0F0F0F);
    num = (num & 0x00FF00FF) + ((num >> 8) & 0x00FF00FF);
    num = (num & 0x0000FFFF) + ((num >> 16) & 0x0000FFFF);
    return num;
}

34. 宏

#define _for(i,a,b) for( int i=(a); i<(b); ++i)
#define __for(i,a,b) for( int i=(a); i<=(b); ++i)
#define mfor(i,a,b) for(int i=(a);i>(b);--i)
#define mmfor(i,a,b) for(int i=(a);i>=(b);--i)

35. 求前缀和

vector<int> pre; // pre[i]=pre[i-1]+w[i]
partial_sum(w.begin(), w.end(), back_inserter(pre)); // vector<int> w

36. 均匀分布 随机生成数

mt19937 gen=random_device{}();
uniform_int_distribution<int> dis(1, accumulate(w.begin(), w.end(), 0)); // 1 ~ vector<int> w 求和
int x = dis(gen);

37. using &&

using u = unsigned int;

39. tuple

tuple<int, int, int> runLoc = make_tuple(hid, cid, hostCoreBlock[hid][cid]++);
int first = get<0>(runLoc[i][j]); // C++ 17 / 20

38. find_if

auto check = [&](string& x){
	  if(x.length()==1)
			  return true;
		return false;
};  
// vector<string>& dic
string s = *find_if(begin(dic), end(dic), check);

40. 函数传参

int binarySearch(int n, function<bool(int)> f) {
        int l = 0, r = n;
        while (l < r) {
            int mid = (l + r) / 2;
            if (f(mid))
                r = mid;
            else
                l = mid + 1;
        }
        return l;
}
vector<vector<int>> d;
// 找第一个大于等于v的 i (d每行最后一个数是升序的)
int i = binarySearch(d.size(), [&](int i) { return d[i].back() >= v; });
// 找i-1行里第一个小于v的数的位置k (d每行降序排列)
int k = binarySearch(d[i - 1].size(), [&](int k) { return d[i - 1][k] < v; });

41. 极值 最值

long a = LONG_MIN;
#include<limits.h> 
#define INT_MAX 2147483647 
#define INT_MIN (-INT_MAX - 1)

42. list

list<int> lst(nums.begin(), nums.end()); // vector<int> nums
auto it = lst.begin();
advance(it, j); // 移动到第j位
shuffled[i] = *it;
lst.erase(it);

43. sleep

// windows
#include<windows.h>
Sleep(2000); 
// linux
#include <unistd.h>
sleep(1); // 秒
usleep(1);// 微秒

44. all_of

int cnt[26]{};
return all_of(cnt, cnt + 26, [](int x){return x >= 0;});

45. 异常捕获

int main()
try {

}
catch (std::exception& e) {
    std::cout<< e.what() << std::endl;
}

46. bind

#include <functional>
int fun(int a, int b, int c, int d);
auto f = std::bind(fun, 100, std::placeholders::_2, 300, std::placeholders::_1);
f(200, 400);// 输出 100 400 300 200

47. for_each

std::for_each(std::begin(arr), std::end(arr), [](int& a) { std::cout << a << "\t"; });

48. 自定义hash

auto hash_fn = [fn = hash<long long>()](const pair<int, int>& o) -> size_t {
    auto& [x, y] = o;
    return fn((long long)x << 20 | y);
};
unordered_set<pair<int, int>, decltype(hash_fn)> hash_blocked(0, hash_fn);
for (const auto& pos: blocked) { // vector<vector<int>> blocked
    hash_blocked.emplace(pos[0], pos[1]);
}

auto hash_p = [](const pair<int, int> &p) -> size_t {
    static hash<long long> hash_ll;
    return hash_ll(p.first + (static_cast<long long>(p.second) << 32));
};
unordered_set<pair<int, int>, decltype(hash_p)> points(0, hash_p);

49. stringstream 字符流

stringstream ss(s); // string s
string word;
while (ss >> word) { // 按空格隔开
    ++freq[move(word)];
}

50. 前导0的个数 和 二进制中1的个数


51. 正则

regex re("\\+|i"); // 根据 + 和 i 分开字符串    num1 string
vector<string> complex1(sregex_token_iterator(num1.begin(), num1.end(), re, -1), std::sregex_token_iterator());

其他

  • long double 可用于 [−263,263]的加减法,只用double却不行,A1065

  • ASCII部分

    ASCII

  • char数组赋值

    char s[14] = {"0123456789JQK"}; //数组长度不可以是s[13],但那下面这种可以是c[13]
    char c[14] = { '0','1','2','3','4','5','6','7','8','9','j','q','k' };
    const char *str[4] = { "aaa", "bbb", "ccc", "ddd"};
    
  • 声明、初始化和释放string二维动态数组

    int n,m; cin>>n>>m; // n行m列的string二维数组
    string** ss=new string*[n];
    for(int i=0;i<n;i++) ss[i]=new string[m];
    
    // 赋值
    string *q=ss[0];   // 1
    string *w=*ss;     // 2
    string *ww=*ss+2;  // 2
    string s[5][6];
    string(*e)[6]=s;   // 3 
    int b[6]={0};
    int *c=b;          // 4
    
    for(int i=0;i<n;i++) delete[] ss[i];
    delete[] ss;
    
    vector<<vector<int>> a( m, vector<int>(n));
    
  • typedef long long ll;


当你走投无路时

  • 考虑变量是否越界访问数组,调大数据表示范围,记得输入(scanf)输出也要改
  • 考虑是否输出有规定位数限制,用 cout 时要用 setw 和 setfill 填充
  • 考虑边界值,比如 +0 与 - 0
  • 看看输出格式,检查单词是否拼错,漏了个字母,大小写
  • 如果在for循环里用了vector的 size() 函数还 -1, 要小心size为 0 时 -1 结果不是负一 ,建议转为int,比如:(int)nums.size() - 1
  • 当用了很多数组或vector、取数组元素时用的下标是另一个数组的值时,要特别注意所代表的含义是否正确
  • 是否改变了输入的数据结构没有还原,比如用Morris算法中序遍历 验证二叉搜索树 一定要还原完再返回

模板

  1. 并查集

    class UF {
    public:
        vector<int> fa;
        vector<int> sz; // 按秩合并
        int n;
        int comp_cnt;
        
    public:
        UF(int _n): n(_n), comp_cnt(_n), fa(_n), sz(_n, 1) {
            iota(fa.begin(), fa.end(), 0);
        }
        
        int findset(int x) {
            return fa[x] == x ? x : fa[x] = findset(fa[x]);
        }
        
        bool unite(int x, int y) {
            x = findset(x);
            y = findset(y);
            if (x == y) {
                return false;
            }
            if (sz[x] < sz[y]) {
                swap(x, y);
            }
            fa[y] = x;
            sz[x] += sz[y];
            --comp_cnt;
            return true;
        }
        
        bool connected(int x, int y) {
            x = findset(x);
            y = findset(y);
            return x == y;
        }
    };
    
  2. 线段树

    struct SegTree{//zkw线段树
        const static int X=1<<17;
        int data[1<<18]={0};
        SegTree(vector<int>&degmap){
            memcpy(data+X,&degmap[0],degmap.size()*sizeof(int));
            for(int i=X-1;i;i--)data[i]=data[i*2]+data[i*2+1];
        }
        void update(int i,int inc){
            for(i+=X;i;i>>=1){
                data[i]+=inc;
            }
        }
        int query(int left,int right){
            if(left>right)return 0;
            if(left==right)return data[left+X];
            left=max(left,0);
            int sum=data[left+=X]+data[right+=X];
            while((left>>1)!=(right>>1)){
                if(left%2==0)sum+=data[left+1];
                if(right%2)sum+=data[right-1];
                left>>=1;
                right>>=1;
            }
            return sum;
        }
    };
    int deg[10000];
    int maxdeg=*max_element(deg,deg+10000);
    vector<int> degmap(maxdeg+1,0);
    for(int i=0;i<10000;i++)
    		degmap[deg[i]]++;
    SegTree T(degmap);
    for(int i=0;i<n;i++){  // 查找deg中两数之和大于sum的对数
        //将自己的度数从度数分布里去除,因为自己不能充当自己的配对
        T.update(deg[i],-1);
        //此时树中的所有度数都是编号比自己大的结点的度数,因为for之前的查询update了
        //累加的范围要求:目标度数加上deg[i]要比sum大
        res+=T.query(sum+1-deg[i],maxdeg); // 区间和
    }
    作者:oldyan
    链接:https://leetcode-cn.com/problems/count-pairs-of-nodes/solution/yi-yu-li-jie-de-xian-duan-shu-zuo-fa-by-5sh80/
    
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    using namespace std;
    
    namespace SegTree {
    	#define maxn 1000000
    	class SegmentTree {
    		#define lson (o<<1)
    		#define rson (o<<1|1)
    		#define mid ((l+r)>>1)
    		public :
    			int addv[maxn], maxv[maxn], minv[maxn], sumv[maxn];
    			int arr[maxn];
    			int N;
    		private:int _max(const int& _, const int& __) { return _>__?_:__; }
    		private:int _min(const int& _, const int& __) { return _<__?_:__; }
    		public : int pushup(int o) {
    			minv[o] = _min(minv[lson], minv[rson]);
    			maxv[o] = _max(maxv[lson], maxv[rson]);
    			sumv[o] = sumv[lson] + sumv[rson];
    			return 0;
    		}
    		public : int pushdown(int o, int l, int r) {
    			if(addv[o] == 0) return -1;
    			addv[lson] += addv[o]; addv[rson] += addv[o];
    			minv[lson] += addv[o]; minv[rson] += addv[o];
    			maxv[lson] += addv[o]; maxv[rson] += addv[o];
    			sumv[lson] += addv[o] * (mid-l+1); sumv[rson] += addv[o] * (r-mid);
    			addv[o] = 0;
    		}
    		public : int Build(int o, int l, int r) {
    			addv[o] = 0;
    			if(l == r) {
    				maxv[o] = arr[l];minv[o] = arr[l];sumv[o] = arr[l];
    				return 0;
    			}
    			Build(lson, l, mid);
    			Build(rson, mid+1, r);
    			pushup(o);
    			return 0;
    		}
    		public : int optadd(int o, int l, int r, int ql, int qr, int addval) {
    			if(ql > r or qr < l) return 0;
    			if(ql <= l and r <= qr) {
    				addv[o] += addval;
    				sumv[o] += addval * (r-l+1);
    				return 0;
    			}
    			pushdown(o, l, r);
    			optadd(lson, l, mid, ql, qr, addval);
    			optadd(rson, mid+1, r, ql, qr, addval);
    			pushup(o);
    		}
    		public : int query_sum(int o, int l, int r, int ql, int qr) {
    			if(ql > r or qr < l) return 0;
    			if(ql <= l and r <= qr) {
    				return sumv[o];
    			}
    			pushdown(o, l, r);
    			return query_sum(lson, l, mid, ql, qr) + query_sum(rson, mid+1, r, ql, qr);
    		}
    		public : int query_min(int o, int l, int r, int ql, int qr) {
    			if(ql > r or qr < l) return 0;
    			if(ql <= l and r <= qr) {
    				return minv[o];
    			}
    			pushdown(o, l, r);
    			return _min(query_min(lson, l, mid, ql, qr), query_min(rson, mid+1, r, ql, qr));
    		}
    		public : int query_max(int o, int l, int r, int ql, int qr) {
    			if(ql > r or qr < l) return 0;
    			if(ql <= l and r <= qr) {
    				return maxv[o];
    			}
    			pushdown(o, l, r);
    			return _max(query_max(lson, l, mid, ql, qr), query_max(rson, mid+1, r, ql, qr));
    		}
    	};
    } 
    //End of SegmentTree
    using namespace SegTree;
    // https://zh.wikipedia.org/wiki/%E7%B7%9A%E6%AE%B5%E6%A8%B9
    
    class NumArray {
    private:
        vector<int> segmentTree;
        int n;
    
        void build(int node, int s, int e, vector<int> &nums) {
            if (s == e) {
                segmentTree[node] = nums[s];
                return;
            }
            int m = s + (e - s) / 2;
            build(node * 2 + 1, s, m, nums);
            build(node * 2 + 2, m + 1, e, nums);
            segmentTree[node] = segmentTree[node * 2 + 1] + segmentTree[node * 2 + 2];
        }
    
        void change(int index, int val, int node, int s, int e) {
            if (s == e) {
                segmentTree[node] = val;
                return;
            }
            int m = s + (e - s) / 2;
            if (index <= m) {
                change(index, val, node * 2 + 1, s, m);
            } else {
                change(index, val, node * 2 + 2, m + 1, e);
            }
            segmentTree[node] = segmentTree[node * 2 + 1] + segmentTree[node * 2 + 2];
        }
    
        int range(int left, int right, int node, int s, int e) {
            if (left == s && right == e) {
                return segmentTree[node];
            }
            int m = s + (e - s) / 2;
            if (right <= m) {
                return range(left, right, node * 2 + 1, s, m);
            } else if (left > m) {
                return range(left, right, node * 2 + 2, m + 1, e);
            } else {
                return range(left, m, node * 2 + 1, s, m) + range(m + 1, right, node * 2 + 2, m + 1, e);
            }
        }
    
    public:
        NumArray(vector<int>& nums) : n(nums.size()), segmentTree(nums.size() * 4) {
            build(0, 0, n - 1, nums);
        }
    
        void update(int index, int val) {
            change(index, val, 0, 0, n - 1);
        }
    
        int sumRange(int left, int right) {
            return range(left, right, 0, 0, n - 1);
        }
    };
    // https://leetcode-cn.com/problems/range-sum-query-mutable/solution/qu-yu-he-jian-suo-shu-zu-ke-xiu-gai-by-l-76xj/
    
  3. 逆元求组合数

//1
ll fac[MAXE],inv[MAXE];
const ll mod=ll(1e9+7);
ll Qpow(ll a,ll p)
{
    ll res=1;
    while(p)
    {
        if(p&1)res=(res*a)%mod;
        a=(a*a)%mod;
        p>>=1;
    }
    return res;
}
ll C(ll n,ll m)//组合数
{
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
fac[0]=1,inv[0]=1;
for(ll i=1;i<MAXE;++i)//预处理阶乘&组合数
{
    fac[i]=fac[i-1]*i%mod;
    inv[i]=Qpow(fac[i],mod-2);
}
//链接:https://www.acwing.com/solution/content/7261/

//2
const int N = 1e5 + 10,M = 2e3 + 10,mod = 1e9 + 7;
int fac[N << 1],invfac[N << 1];
int C(int n,int m){return n<m?0:(long long)fac[n]*invfac[m]%mod*invfac[n-m]%mod;}
void init(){
   fac[0]=invfac[0]=invfac[1]=1;
   for(int i=1;i<=2e5 + 10;i++)fac[i]=(long long)fac[i-1]*i%mod;
   for(int i=2;i<=2e5 + 10;i++)invfac[i]=(long long)(mod-mod/i)*invfac[mod%i]%mod;
   for(int i=2;i<=2e5 + 10;i++)invfac[i]=(long long)invfac[i-1]*invfac[i]%mod;
}
//链接:https://www.acwing.com/solution/content/17704/

  1. 快读快写
#define ll long long int
inline ll read(){
   ll s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
inline void out(ll a)
{
    if(a>=10)out(a/10);
    putchar(a%10+'0');
}
  1. AVL

AVL

  1. 树状数组

    class StreamRank {
    public:
        int arr[50005];
        StreamRank() {
            for(int i=0;i<50005;i++){
                arr[i]=0;
            }
        }
        
        void track(int x) {
            x++;
            for(int i=x;i<50005;i+=i&(-i)){
                arr[i]++;
            }
            return ;
        }
        
        int getRankOfNumber(int x) {
            int res=0;
            for(int i=x+1;i;i-=i&(-i)){
                res+=arr[i];
            }
            return res;
        }
    };
    
    /**
     * Your StreamRank object will be instantiated and called as such:
     * StreamRank* obj = new StreamRank();
     * obj->track(x);
     * int param_2 = obj->getRankOfNumber(x);
     */
    
    class NumArray { // 求区间和
    private:
        vector<int> tree;
        vector<int> &nums;
    
        int lowBit(int x) {
            return x & -x;
        }
    
        void add(int index, int val) {
            while (index < tree.size()) {
                tree[index] += val;
                index += lowBit(index);
            }
        }
    
        int prefixSum(int index) {
            int sum = 0;
            while (index > 0) {
                sum += tree[index];
                index -= lowBit(index);
            }
            return sum;
        }
    
    public:
        NumArray(vector<int>& nums) : tree(nums.size() + 1), nums(nums) {
            for (int i = 0; i < nums.size(); i++) {
                add(i + 1, nums[i]);
            }
        }
    
        void update(int index, int val) {
            add(index + 1, val - nums[index]);
            nums[index] = val;
        }
    
        int sumRange(int left, int right) {
            return prefixSum(right + 1) - prefixSum(left);
        }
    };
    
    作者:LeetCode-Solution
    链接:https://leetcode-cn.com/problems/range-sum-query-mutable/solution/qu-yu-he-jian-suo-shu-zu-ke-xiu-gai-by-l-76xj/
    
    // 区间修改,单点查询(此处用差分数组)
    add(l, val); add(r+1, -val);
    ans = nums[x]+prefixSum(x);
    
    // 区间修改,区间查询
    class TreeArray {
    private:
        int n;
        vector<int> tree1;
        vector<int> tree2;
    
        inline int lowbit(int x) {
            return x & (-x);
        }
    
        void updata(int i, int val) {
            for (int p = i; i <= n; i += lowbit(i)) {
                tree1[i] += val;
                tree2[i] += p*val;
            }
        }
    
        int query(int i) {
            int sum = 0;
            for (int n = i; i > 0; i -= lowbit(i)) {
                sum += (n+1)*tree1[i] - tree2[i];
            }
            return sum;
        }
    
    public:
        TreeArray() {}
        TreeArray(int n):n(n), tree1(n+1), tree2(n+1) {}
    
        // 区间修改
        void rangeUpdata(int left, int right, int val) {
            updata(left, val);
            updata(right+1, -val);
        }
        // 区间查询
        int rangeQuery(int left, int right) {
            return query(right) - query(left-1);
        }
    
    };
    

在这里插入图片描述

        $=\sum_i \{(n+1)D[i]- iD[i]\}$ 
  1. 字典树模板

    struct TrieNode {
        string word;
        unordered_map<char,TrieNode *> children;
        TrieNode() {
            this->word = "";
        }   
    };
    
    void insertTrie(TrieNode * root,const string & word) {
        TrieNode * node = root;
        for (auto c : word){
            if (!node->children.count(c)) {
                node->children[c] = new TrieNode();
            }
            node = node->children[c];upper_bound
        }
        node->word = word;
    }
    
    // 数组版
    constexpr int MN = 8E4, M = 26, ML = 1000 + 1;
    int top, tree[MN][M];
    bool isEnd[MN];// vis[ML];
    
    int getNext() {
        isEnd[++top] = 0;
        memset(tree[top], 0, sizeof tree[top]);
        return top;
    }
    
    void insert(const string& s) {
        int rt = 1;
        for (char c : s) {
            c -= 'a';
            if (tree[rt][c]) rt = tree[rt][c];
            else rt = tree[rt][c] = getNext();
        }
        isEnd[rt] = 1;
    }
    

Thank you very much for your reward !

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bugs清道夫

来自清道夫的谢意,susga

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值