GithubHelp home page GithubHelp logo

algorithms-notebook's People

Contributors

animeshsinha1309 avatar dixitgarg059 avatar gaurangtandon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

algorithms-notebook's Issues

Code for finding diameter of tree

int diameter(int node, VI &visited, VVI &adj, VI &distances) {
    VI seen = {};

    queue<int> q;
    q.push(node);
    distances[node] = 0;
    visited[node] = true;
    int farthest = node;
    
    while(!q.empty()) {
        auto node = q.front();
        q.pop();

        seen.push_back(node);
        for (auto neigh : adj[node]) {
            if (not visited[neigh]) {
                visited[neigh] = true;
                distances[neigh] = 1 + distances[node];
                if (distances[farthest] < distances[neigh]) farthest = neigh;
                q.push(neigh);
            }
        }
    }

    for (auto x : seen) distances[x] = INT_MIN, visited[x] = false;
    q.push(farthest);
    distances[farthest] = 0;
    visited[farthest] = true;
    
    while(!q.empty()) {
        auto node = q.front();
        q.pop();

        seen.push_back(node);
        for (auto neigh : adj[node]) {
            if (not visited[neigh]) {
                visited[neigh] = true;
                distances[neigh] = 1 + distances[node];
                if (distances[farthest] < distances[neigh]) farthest = neigh;
                q.push(neigh);
            }
        }
    }

    return distances[farthest];
}

Call it like this:

    VI visited(n + 1, false);
    VI distances(n + 1, 0);
    for (int i = 1; i <= n; i++) {
        if (!visited[i]) {
            diameter(i, visited, adj, distances);
        }
    }

Tested on problem 455C

Find a place to put this in our repo. Not everything needs to be in the icpc notebook, some things can be there just for easy copy-paste :P

Unclear usage for HopCroft Karp

It would be great if there could be few comments here and there on how to use the HopcroftKarp code for someone who knows what the algorithm is and how it works. Specifically, please explain: size_u, size_v, nil, pair_u, pair_v, dist.

[WIP] Treaps tested implementation

This file contains many helper functions so that when in regionals we don't have to do deal with off by one errors.
Currently tested on some questions from VJudge

The following treap tracks minima in subtree.

#include <bits/stdc++.h>
#ifdef ONLINE_JUDGE
#define endl "\n"
#endif
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int, int> PII;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// default rand() may generate only till 32767 which is not big enough for
// large treaps

template <typename T>
class Node {
   private:
    typedef Node<T> *pnode;
    T val, lazy, mi;
    bool reverse;

    int prior, size;
    Node *l, *r;

    // CONFIG START
    static T get_cum_value(pnode t) {
        return t ? t->val : INT_MIN;
    }
    static void upd_lazy(pnode t, T val) {
        if (t)
            t->lazy += val;
    }
    // make sure to refresh ALL computable properties
    // because the pointers are being moved around all the times,
    // any unrefreshed property (even when l and r are both null)
    // can cause major issues
    static void refresh(pnode t) {
        if (t) {
            t->size = get_size(t->l) + 1 + get_size(t->r);
            t->lazy = 0;
            t->reverse = false;
            auto l = t->l, r = t->r;
            t->mi = min({l ? l->mi : INT_MAX, r ? r->mi : INT_MAX, t->val});
        }
    }
    static void pushlazy(pnode t) {
        if (!t)
            return;
        if (t->reverse) {
            swap(t->l, t->r);
            if (t->l)
                t->l->reverse = not t->l->reverse;
            if (t->r)
                t->r->reverse = not t->r->reverse;
            t->reverse = false;
        }
        if (t->lazy) {
            t->val += t->lazy;
            t->mi += t->lazy;
            if (t->l)
                t->l->lazy += t->lazy;
            if (t->r)
                t->r->lazy += t->lazy;
            t->lazy = 0;
        }
    }
    // CONFIG END

    // This is an insert by "value" (not position)
    // PRESUMPTION (necessary?): it->size == 1
    static void insert(pnode &t, pnode it) {
        pushlazy(t);
        if (!t)
            t = it;
        else if (it->prior > t->prior)
            split_by_key(t, it->l, it->r, it->val), t = it;
        else
            insert(t->val < it->val ? t->r : t->l, it);
        refresh(t);
    }

   public:
    static void insert_at_pos(pnode &t, T val, int pos) {
        Node<int> *l, *r;
        split(t, l, r, pos - 1);
        append(l, val);
        merge(t, l, r);
    }
    // insert at end
    static void append(pnode &t, T val) {
        merge(t, t, new Node(val));
    }

    static void delete_at_pos(pnode &t, int pos) {
        Node<int> *l, *mid, *r;
        split(t, l, r, pos - 1);
        split(r, mid, r, 1);
        merge(t, l, r);
    }

    // element at `pos` (1-indexed) goes to "l"
    static void split(pnode t, pnode &l, pnode &r, int pos) {
        pushlazy(t);
        if (!t)
            return void(l = r = NULL);
        int ihave = get_size(t->l) + 1;
        if (ihave > pos)
            split(t->l, l, t->l, pos), r = t;
        else
            split(t->r, t->r, r, pos - ihave), l = t;
        refresh(t);
    }
    static int get_size(pnode t) {
        return t ? t->size : 0;
    }
    // elements with value `key` belong to left
    static void split_by_key(pnode t, pnode &l, pnode &r, T key) {
        pushlazy(t);
        if (!t)
            l = r = nullptr;
        else if (t->val <= key)
            split_by_key(t->r, t->r, r, key), l = t;
        else
            split_by_key(t->l, l, t->l, key), r = t;
        refresh(t);
    }

    // this merge maintains the order of the nodes
    // i.e., the first X elements in t are all from l
    // and the remaining all are from r
    static void merge(pnode &t, pnode l, pnode r) {
        pushlazy(t);
        pushlazy(l);
        pushlazy(r);
        if (not l or not r)
            t = l ? l : r;
        else if (l->prior > r->prior)
            merge(l->r, l->r, r), t = l;
        else
            merge(r->l, l, r->l), t = r;
        refresh(t);
    }
    static void insert(pnode &t, T val) {
        insert(t, new Node(val));
    }
    static bool has(pnode &t, T key) {
        pushlazy(t);
        if (!t)
            return false;
        if (t->val == key)
            return true;
        return (t->val < key) ? has(t->r, key) : has(t->l, key);
    }
    static void erase(pnode &t, T key) {
        pushlazy(t);
        if (!t)
            return;
        else if (t->val == key) {
            pnode x = t;
            merge(t, t->l, t->r);
            delete x;
        } else
            erase(t->val < key ? t->r : t->l, key);
        refresh(t);
    }
    static void unite(pnode &t, pnode l, pnode r) {
        pushlazy(t);
        pushlazy(l);
        pushlazy(r);
        if (!l or !r)
            return void(t = l ? l : r);
        Node *lt, *rt;
        if (l->prior < r->prior)
            swap(l, r);
        split_by_key(r, lt, rt, l->val);
        unite(l->l, l->l, lt);
        unite(l->r, l->r, rt);
        t = l;
        refresh(t);
    }
    Node(T _val) {
        mi = val = _val;
        size = 1;
        prior = rng();
        lazy = 0;
        reverse = false;
        l = r = nullptr;
    }

    static T range_query(pnode t, int ql, int qr) {  // [ql, qr]
        Node *l, *mid, *r;  // the `t` pointer is reused
        split(t, l, mid, ql - 1);
        split(mid, t, r, qr - ql + 1);
        auto ans = get_cum_value(t);
        merge(mid, l, t);
        merge(t, mid, r);
        return ans;
    }

    static void range_update(pnode t, int ql, int qr, T val) {  // [l, r]
        Node *l, *mid, *r;
        split(t, l, mid, ql - 1);
        split(mid, t, r, qr - ql + 1);
        upd_lazy(t, val);
        merge(mid, l, t);
        merge(t, mid, r);
    }
    static void range_reverse(pnode t, int ql, int qr) {  // [l, r]
        Node *l, *mid, *r;
        split(t, l, mid, ql - 1);
        split(mid, t, r, qr - ql + 1);
        rev(t);
        merge(mid, l, t);
        merge(t, mid, r);
    }

    static void inorder(pnode t) {
        pushlazy(t);
        if (!t)
            return;
        inorder(t->l);
        cout << t->val << " ";
        inorder(t->r);
    }

    static void rev(pnode t) {
        pushlazy(t);
        if (t)
            t->reverse = not t->reverse;
    }

    // a[0] goes to a[moves]
    static void rotate_forward(pnode t, int moves) {
        if (not get_size(t))
            return;
        moves %= get_size(t);
        if (moves) {
            int newfirst = get_size(t) - moves + 1;
            Node<int> *l, *r;
            t->split(t, l, r, newfirst - 1);
            t->merge(t, r, l);
        }
    }
    static void rotate_subseq_forward(pnode t, int ql, int qr, int moves) {
        Node *l, *mid, *r;
        split(t, l, mid, ql - 1);
        split(mid, t, r, qr - ql + 1);
        rotate_forward(t, moves);
        merge(mid, l, t);
        merge(t, mid, r);
    }
};

void solve() {
    int n, q, m;
    cin >> n >> q >> m;

    Node<int> *treap = nullptr;

    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        treap->append(treap, x);
    }

    while (q--) {
        int t, l, r;
        cin >> t >> l >> r;

        if (t == 1)
            treap->rotate_subseq_forward(treap, l, r, 1);
        else
            treap->range_reverse(treap, l, r);
    }

    while (m--) {
        int x;
        cin >> x;
        cout << treap->range_query(treap, x, x) << " ";
    }
    cout << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    // int t;cin >> t;while(t--)
    solve();
    return 0;
}

Matrix multiplication and geometric sum (finite terms) code

Apologies for the spam. I intend to organize all this stuff sometime soon.

#include <bits/stdc++.h>
#ifdef ONLINE_JUDGE
#define endl "\n"
#endif
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int, int> PII;

const int mod = 10;

VVI ide(int sz) {
    VVI res(sz, VI(sz, 0));
    for (int i = 0; i < sz; i++) res[i][i] = 1;
    return res;
}

VVI mult (const VVI &a, const VVI &b) {
    int r = a.size();
    int c = b.front().size();
    VVI res(r, VI(c, 0));
    int mid = a.front().size();
    
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            for (int k = 0; k < mid; k++) {
                res[i][j] += 1ll * a[i][k] * b[k][j] % mod;
                res[i][j] %= mod;
            }
        }
    }

    return res;
}

VVI po(const VVI &mat, int y) {
    VVI res = ide(mat.size());
    VVI x = mat;

    while (y) {
        if (y & 1) {
            res = mult(res, x);
        }
        y >>= 1;
        x = mult(x, x);
    }

    return res;
}

// n is number of terms, gp starts with identity matrix
VVI gpsum(const VVI &mat, int n) {
    int r = mat.size(), c = mat.front().size();
    assert(r == c);

    if (n == 0) return VVI(r, VI(r, 0));
    if (n == 1) return ide(r);

    if (n & 1) {
        VVI mat2 = gpsum(mat, n - 1);
        mat2 = mult(mat, mat2);
        for (int i = 0; i < r; i++) mat2[i][i] += 1;
        return mat2;
    }

    VVI a = gpsum(mat, n / 2);
    VVI a2 = po(mat, n / 2);
    VVI b = mult(a2, a);
    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++)
            a[i][j] += b[i][j], a[i][j] %= mod;
    return a;
}

void solve() {
    int n, k; cin >> n >> k;
    if (n == 0) exit(0);

    VVI mat(n, VI(n, 0));
    for (auto &x : mat) for (auto &y : x) cin >> y;

    mat = gpsum(mat, k + 1);
    for (int i = 0; i < n; i++) mat[i][i] -= 1, mat[i][i] += 10, mat[i][i] %= 10;

    for (auto &x : mat) { int i = -1; for (auto &y : x) ++i, cout << y << " \n"[i == n - 1]; }
    cout << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    while(true)
        solve();
    return 0;
}

Verified on UVa Power of a Matrix (11149).

MCMF tested implementation

From Anurudh. Tested on:

  1. 1510B Button Lock (non-binary costs)
  2. SPOJ - GREED (bidirectional graphs)
  3. Kattis: https://open.kattis.com/problems/mincostmaxflow

Code:

template <typename FLOW, typename COST>
struct MCMF {
  const COST INFC = 1e9, EPSC = 0;
  const FLOW INFF = 1e9, EPSF = 0;
  struct Edge {
    int from, to;
    FLOW flow, cap;
    COST cost;
  };
  int nodes, src, dest, m = 0;
  vector<vector<int>> adj;
  vector<Edge> edges;
  void add(int u, int v, FLOW cap, COST cost) {
    edges.push_back({u, v, 0, cap, cost});
    adj[u].push_back(m++);
    edges.push_back({v, u, 0, 0, -cost});
    adj[v].push_back(m++);
  }
  vector<COST> dis;
  vector<bool> inQ;
  VI par;
  pair<FLOW, COST> SPFA() {
    fill(dis.begin(), dis.end(), INFC);
    fill(inQ.begin(), inQ.end(), false);
    queue<int> Q;
    dis[src] = 0;
    Q.push(src);
    inQ[src] = true;
    while (!Q.empty()) {
      int u = Q.front();
      Q.pop();
      inQ[u] = false;
      for (int i : adj[u]) {
        auto &e = edges[i];
        if (e.cap - e.flow > EPSF && dis[e.to] - (dis[u] + e.cost) > EPSC) {
          dis[e.to] = dis[u] + e.cost;
          par[e.to] = i;
          if (!inQ[e.to]) {
            Q.push(e.to);
            inQ[e.to] = true;
          }
        }
      }
    }
    if (dis[dest] + EPSC >= INFC) return {0, 0};
    FLOW aug = INFF;
    for (int u = dest; u != src; u = edges[par[u]].from) {
      aug = min(aug, edges[par[u]].cap - edges[par[u]].flow);
    }
    for (int u = dest; u != src; u = edges[par[u]].from) {
      edges[par[u]].flow += aug;
      edges[par[u] ^ 1].flow -= aug;
    }
    return {aug, aug * dis[dest]};
  }
  MCMF(int n, int s, int t)
      : nodes(n), src(s), dest(t), adj(n), dis(n), inQ(n), par(n) {}
  pair<FLOW, COST> mincostmaxflow() {
    pair<FLOW, COST> ans(0, 0);
    while (true) {
      auto cur = SPFA();
      if (cur.first <= EPSF) break;
      ans.first += cur.first;
      ans.second += cur.second;
    }
    return ans;
  }
};

Consistent Use of Infinity

We have a lot of infinities floating around in the code, some for integers, and some for floats. All of them are inconsistent and use different constants from the C library. We need to decide on what to use and convert everything to it.

Make all graphs use one-indexed notation

I have been using one-indexed node numbering for so long and haven't broken a sweat.

It's just so much easier to use since even all the questions use one-indexing you don't have to worry about subtracting anything while reading input and using it.

Having to subtract 1 every time after reading input feels pointless once you get used to this.

Can we just do a quick run through of our codes for enforcing this notation? Or contrary thoughts?

Treaps: Augmentable Binary Search Trees

We need to implement all functionality in Treaps.

The basic portion would include:

  • Insert
  • Delete
  • Find

The special operations will include:

  • Split
  • Merge

We need possible augmentation on all nodes.

A Foray into DP Optimizations

We need to get some theory and some practice in the following optimisations:

  • Convex Hull Trick
  • Divide and Conquer Trick
  • Knuth Optimisation
  • 1D-1D Optimisation
  • IOI Aliens Trick
    We also need to see enough problems that quadrangle inequalities are easy to spot. I will keep adding some text and code, need other perspectives too.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.