C++ & STL

來自蛋餅的提醒

  • 每個容器都有empty(),表示容器是不是空的;如果試圖存取空容器的值可能會RE或取到亂數
  • 只有序列容器有索引值,當然是左閉右開,小心別讓i<0或i>=size()
  • 避免從空容器中讀取或pop東西
  • 對於序列容器來說,他們的第一項和最後一項分別是front()和back()
  • queue是front(), stack是top()

Iterator

  • 類似指標,指向一個位置,用 *it 存取那個變數
  • set、map 等不能直接用 i=[0, size()) 存取
  • 利用 [ begin(), end() ) 遍歷
int main(){
    vector<int> v;
    
    for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
        cin >> *it;
    
    for(auto It = v.begin(); It != v.end() ; ++It)
        cout << *It << ' ';
}

*rbegin()、rend() 是反向迭代器 (C++17)

range-based for (C++14)

#include <bits/stdc++.h>
using namespace std;

int main(){
    vector<int> v;
    set<int> st;
    map<int, int> mp;
    
    for(int i: v)
        cout << i << '\n';
    for(auto j: st)
        cout << j << '\n';
    for(auto k: mp)
        cout << k.first << ' ' << k.second << '\n';
}

structure binding (C++17)

#include <bits/stdc++.h>
using namespace std;

struct Node{
    int val, sum, max_val, min_val;
};
int main(){
    
    vector<pair<int, int>> vp;
    for(auto [F, S]: vp)
        cout << F << ' ' << S << '\n';
        
    vector<Node> v;
    for(auto [a, b, c, d]: v)
        cout << a << ' ' << b << ' ' << c << ' ' << d << '\n';
}

reference

#include <iostream>
using namespace std;

void swap(int &a, int &b){
    if(a != b)
        a ^= b ^= a ^= b;
}
int main(){
    int x, y;
    cin >> x >> y;
    swap(x, y);
    cout << x << ' ' << y << '\n';
}

全部耨在一起

#include <bits/stdc++.h>
using namespace std;

struct Node{
    int x, y;
    bool equal;
};
int main(){
    vector<int> arr(10);
    for(int &i: arr)
        cin >> i;
    
    int n; cin >> n;
    vector<pair<int, int>> brr;
    brr.resize(n);
    for(auto &[F, S]: brr)
        cin >> F >> S;
        
    vector<Node> v(100);
    for(auto &[a, b, c]: v){
        cin >> a >> b;
        c = (a == b);
    }
}

unordered

unordered_set、unordered_map

  • 容器內部沒有排序過
  • 資料用 hash 方式丟進容器
  • 貌似是 \(\mathcal{O}(N)\) 複雜度
  • 有時候常數比單純 set、map 好

multi

multiset、multimap

  • 可以放重複的東西
  • multimap 存在的意義?

<algorithm>

Function S

  • max(a, b) / min(a, b)
  • max({a,b,c,...}) / min({a,b,c,...})
  • swap(a, b)
  • __gcd(a, b)

Function S

  • sort(begin, end, compare)
  • stable_sort(begin, end, compare)
  • lower_bound(begin, end, value) *
  • upper_bound(begin, end, value) *
  • binary_search(begin, end, value) *
  • max_element(begin, end) *
  • min_element(begin, end) *

* 代表回傳 iterator

Function S

set、map 用 member function

int main(){
    set<int> st;
    st.insert(1);
    st.insert(5);
    st.insert(7122);
    
    auto it = st.lower_bound(5);
    auto It = st.find(7122);
    int max_val = *st.begin();
    int min_val = *prev(st.end());
}

Function S

  • fill(begin, end, value)
  • reverse(begin, end)
  • unique(begin, end) *
  • next_permutation(begin, end)
  • prev_permutation(begin, end)
  • random_shuffle(begin, end)
  • merge(begin1, end1, begin2, end2, begin3, cmp)

* 代表回傳 iterator

Function S

  • __lg(x)
  • __builtin_clz(x)
  • __builtin_popcount(x)

lambda expression

int main(){

    int arr[100001];
    sort(arr, arr + 100001, [](int a, int b){
        return a > b;
    });


    vector<int> v;
    sort(v.begin(), v.end(), [&](int a, int b){
        return a > b;
    });
}

lambda expression

int main(){

    auto add = [&](int a, int b){
        return a + b;
    };
    
    int x, y;
    cin >> x >> y;
    cout << add(x, y) << '\n';
}

離散化

#include <bits/stdc++.h>
using namespace std;

vector<int> a, b;
int main(){
    int n;
    cin >> n;
    a.resize(n);
    
    for(int &i: a){
        cin >> i;
        b.emplace_back(i);
    }
    sort(b.begin(), b.end());
    b.resize(unique(b.begin(), b.end())-b.begin());
    for(int &i: a){
        i = lower_bound(b.begin(), b.end(), i)-b.begin();
    }
}

random

  • rand()
  • 內建 mt19937()
  • 手刻 random()
#include <cstdlib>
#include <ctime>
using namespace std;

int main(){
    srand(time(NULL));
    
    int arr[101];
    for(int i=0 ; i<100 ; ++i)
        arr[i] = rand();
}
#include <chrono>
#include <random>
using namespace std;

int main(){
    auto seed = chrono::system_clock::now().time_since_epoch().count();
    mt19937 ran(seed);
    
    int arr[101];
    for(int i=0 ; i<100 ; ++i)
        arr[i] = ran();
}
unsigned ran(){
    static unsigned x = 19;
    return ++(x *= 0xdefaced);
}
int main(){
    unsigned arr[101];
    for(int i=0 ; i<100 ; ++i)
        arr[i] = ran();
}

<bitset>

<bitset>

#include <iostream>
#include <bitset>
using namespace std;

int main(){
    bitset<10> b(12345);
    cout << b.to_string() << '\n';
    
    b.reset();
    b.set();
    cout << b.to_ulong() << '\n';
    
    b[0] = 1, b[1] = 0;
    cout << b[2] << '\n';
    
    b <<= 2;
    // & | ^ << >> ~
}

<cstring>

<cstring>

唯一的用處

#include <cstring>
using namespace std;

int a[10001];
int b[101][101][101];
int main(){
    memset(a, 0, sizeof(a));
    memset(b, -1, sizeof(b));
}

<cmath>

<cmath>

  • abs(x)
  • floor(x) / ceil(x) / round(x)
  • sqrt(x) / pow(x, y)

\(\Gamma(x)\)

\((x-1)!\)

  • tgamma(x)
  • lgamma(x)

\(\Gamma(x)\)

\(\ln (\Gamma (x))\)

<cctype>

<cctype>

唯一的用處

  • tolower(c)
  • toupper(c)

IO

"string constant"[option]

#include <iostream>
using namespace std;

int main(){
    int arr[101];
    for(int i=0 ; i<100 ; ++i)
        cout << arr[i] << " \n"[i == 99];
}

不輸出多餘行尾空白

<iomanip>

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main(){
    double PI = acos(-1);
    cout << fixed << setprecision(10) << PI << '\n';
}

固定精度

fixed: 不用科學記號 / scientific 用科學記號

optimize

ios_base::sync_with_stdio(false);
cin.tie(0);
// use '\n' instead of endl

C++ & STL

By youou

C++ & STL

  • 250