animeshsinha1309 / algorithms-notebook Goto Github PK
View Code? Open in Web Editor NEWThe team notebook to keep all template code and notes in.
The team notebook to keep all template code and notes in.
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
https://github.com/ouuan/segmentTree/blob/master/README.md#Demos (from here- https://codeforces.com/blog/entry/70467)
We have to see if it better than our current segment tree and in what way.
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
.
Possible sources
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;
}
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).
https://codeforces.com/blog/entry/22072 (just keeping it here for whenever we want to integrate we can find it)
Reference code: https://codeforces.com/contest/915/submission/35567497
Pros: doesn't get memory and time limit. See my submissions on problem E :sadface:
At some point in time, I want to compare our implementation of a persistent segtree, with the one present at this IDEone link (found it here, solves SPOJ DQUERY), and use whichever is neater
Till we get online-judge-verifier to work...
HopcroftKarp
KMP
Need to also track that date of verification >= modification time of the concerned file. (also check that the source code is similar)
Can I write a bash script for checking that?
It is as good as our current approach and also generates cool looking documentation.
Example: https://beet-aizu.github.io/library/library/combinatorics/partition.cpp.html
It only supports two judges though, however, we can use this guys (beet-aizu's) problem links to find relevant judge problems for testing our own codes.
From Anurudh. Tested on:
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;
}
};
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.
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?
We need to implement all functionality in Treaps.
The basic portion would include:
The special operations will include:
We need possible augmentation on all nodes.
We need to get some theory and some practice in the following optimisations:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.