Algo Snippet

Posted on Jul 25, 2022

Algebra

Sieve of Primes

vector<int> pr;

vector<int> allprimes(int n) { // O(N log log N)
    vector<bool> is_prime(n+1, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i * i <= n; i++) {
    	if (is_prime[i]) {
        	for (int j = i * i; j <= n; j += i)
        		is_prime[j] = false;
        }
    }
    for (int i = 2; i <= n; ++i) {
        if (is_prime[i]) 
            pr.push_back(i);
    }
}

Get All Factorization

vector<int> spf;
vector<int> pr;

void sieve(int n) { // O(N)
    spf.resize(n+1);
    pr.clear();
    for (int i = 2; i <= n; ++i)
        spf[i] = i;

    for (int i = 2; i * i <= n; i++) {
        if (spf[i] != i) continue; 
        pr.push_back(i);
        for (int j = 0; j < pr.size() && pr[j] <= spf[i] && i*pr[j] <= n; ++j) {
            spf[i * pr[j]] = pr[j];
        }
    }
}

vector<int> getFactors(int n) { // O(logN)
    vector<int> factors;
    while (n > 1) {
        factors.push_back(spf[n]);
        n /= spf[n];
    }
    return factors;
}

Data Structure

Sparse Table

class SparseTable {
    using llong = long long;
    llong ** ST; 
    llong * LOG;
    llong N, K;
    SparseTable(llong n, llong * array) {
        N = n;
        // compute log
        LOG = new llong[N+1];
        LOG[1] = 0;
        for (llong i = 2; i <= MAXN; i++)
            LOG[i] = LOG[i/2] + 1;
        K = LOG[N] + 1;
        ST = new llong*[N+1];
        for (llong i = 0; i <= N; ++i)
            ST[i] = new llong*[K];
        // precompute
        for (llong i = 0; i < N; i++)
		    ST[i][0] = f(array[i]);   // change f
        for (llong j = 1; j <= K; j++)
    		for (llong i = 0; i + (1 << j) <= N; i++)
        		ST[i][j] = f(ST[i][j-1], ST[i + (1 << (j - 1))][j - 1]);
    }
    llong ranQ(llong L, llong R) {
        llong ans = 0; // change initial
        for (llong j = K; j >= 0; j--) {
            if ((1 << j) <= R - L + 1) {
                ans = f( ans, ST[L][j] ); // change f
                L += 1 << j;
            }
        }
        return ans;
    }
    llong ranQfast(llong L, llong R) {
        llong j = LOG[R - L + 1];
        return f( st[L][j], st[R - (1 << j) + 1][j] ); // change f
    }
};
long long st[N+1][K]; // take K >= log_2 N

// precompute
for (int i = 0; i < N; i++)
    st[i][0] = f(array[i]);

for (int j = 1; j <= K; j++)
    for (int i = 0; i + (1 << j) <= N; i++)
        st[i][j] = f(st[i][j-1], st[i + (1 << (j - 1))][j - 1]);

int log[MAXN+1];
log[1] = 0;
for (int i = 2; i <= MAXN; i++)
    log[i] = log[i/2] + 1;

// range query for log n
long long sum = 0;
for (int j = K; j >= 0; j--) {
    if ((1 << j) <= R - L + 1) {
        sum += st[L][j];
        L += 1 << j;
    }
}

// range query for O(1)
int j = log[R - L + 1];
int minimum = min(st[L][j], st[R - (1 << j) + 1][j]);

Union Find

class UnionFind {
    vector<int> parent, size;
public:
    UnionFind(int n) {
        parent.resize(n); size.resize(n);
        for (int i = 0; i < n; i++) {
            parent[i] = i; size[i] = 1;
        }
    }
    int find(int x) {
        if (x == parent[x]) return x;
        return parent[x] = find(parent[x]); 
    }
    bool Union(int u, int v) {
        int pu = find(u), pv = find(v);
        if (pu == pv) return false; // Return False if u and v are already union
        if (size[pu] > size[pv]) { // Union by larger size
            size[pu] += size[pv];
            parent[pv] = pu;
        } else {
            size[pv] += size[pu];
            parent[pu] = pv;
        }
        return true;
    }
};