0% found this document useful (0 votes)
22 views

Stanford Python Codebook

Stanford ICPC Python Codebook

Uploaded by

scl019
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views

Stanford Python Codebook

Stanford ICPC Python Codebook

Uploaded by

scl019
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 25

1

IIIT-Delhi - Cogito Ergo Error

Contents 7.1 2-SAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19


7.2 Merge Insertion . . . . . . . . . . . . . . . . . . . . . . . 20
7.3 DP Optimizations . . . . . . . . . . . . . . . . . . . . . . 21
1 Combinatorial optimization 1 7.4 Convex Hull Trick (Dynamic) . . . . . . . . . . . . . . . . 21
1.1 Dinic’s . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 7.5 Convex Hull Trick (Static) . . . . . . . . . . . . . . . . . 22
1.2 Min-cost Circulation . . . . . . . . . . . . . . . . . . . . 2 7.6 BigInt library . . . . . . . . . . . . . . . . . . . . . . . . 22
1.3 Edmonds Max Matching . . . . . . . . . . . . . . . . . . 3 7.7 Manachers algorithm . . . . . . . . . . . . . . . . . . . . 23
1.4 Hungarian Min-cost . . . . . . . . . . . . . . . . . . . . . 4 7.8 Dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.5 Konig’s Theorem (Text) . . . . . . . . . . . . . . . . . . . 4 7.9 Bitset (Text) . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.6 Minimum Edge Cover (Text) . . . . . . . . . . . . . . . . 4 7.10 Template . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
7.11 Numerical Integration . . . . . . . . . . . . . . . . . . . . 25
2 Geometry 5
2.1 Miscellaneous geometry . . . . . . . . . . . . . . . . . . 5
2.2 3D geometry . . . . . . . . . . . . . . . . . . . . . . . . . 61 Combinatorial optimization
2.3 Convex hull . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.4 Min Enclosing Circle . . . . . . . . . . . . . . . . . . . . 71.1 Dinic’s
2.5 Pick’s Theorem (Text) . . . . . . . . . . . . . . . . . . . . 8 struct Dinic {
2.6 Slow Delaunay triangulation . . . . . . . . . . . . . . . . 8 struct Edge {
int u, v;
long long cap, flow;
3 Numerical algorithms 8 Edge() {}
3.1 Pollard Rho . . . . . . . . . . . . . . . . . . . . . . . . . 8 Edge(int u, int v, long long cap): u(u), v(v), cap(
3.2 Simplex algorithm . . . . . . . . . . . . . . . . . . . . . . 9 cap), flow(0) {}
3.3 Reduced row echelon form . . . . . . . . . . . . . . . . . 10 };
int N;
3.4 Fast Fourier transform . . . . . . . . . . . . . . . . . . . . 10 vector<Edge> E;
3.5 Number Theoretic transform . . . . . . . . . . . . . . . . 11 vector<vector<int>> g;
3.6 Discrete Logarithm . . . . . . . . . . . . . . . . . . . . . 12 vector<int> d, pt;
3.7 Mobius Inversion (Text) . . . . . . . . . . . . . . . . . . . 12 Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}
3.8 Burnside Lemma (Text) . . . . . . . . . . . . . . . . . . . 12
3.9 Number Theory (Modular, CRT, Linear Diophantine) . . . 12 void AddEdge(int u, int v, long long cap) {
if (u != v) {
E.emplace_back(Edge(u, v, cap));
4 Graph algorithms 13 g[u].emplace_back(E.size() - 1);
4.1 Dynamic Connectivity . . . . . . . . . . . . . . . . . . . 13 E.emplace_back(Edge(v, u, 0));
4.2 Bridges . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 g[v].emplace_back(E.size() - 1);
}
4.3 Strongly connected components . . . . . . . . . . . . . . 14 }
bool BFS(int S, int T) {
5 String Stuff 14 queue<int> q({S});
5.1 Suffix Automaton . . . . . . . . . . . . . . . . . . . . . . 14 fill(d.begin(), d.end(), N + 1);
5.2 Suffix array . . . . . . . . . . . . . . . . . . . . . . . . . 15 d[S] = 0;
5.3 Z Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . 15 while(!q.empty()) {
int u = q.front(); q.pop();
5.4 KMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 if (u == T) break;
5.5 String Hashing . . . . . . . . . . . . . . . . . . . . . . . . 16 for (int k: g[u]) {
5.6 Palindrome DSU . . . . . . . . . . . . . . . . . . . . . . 16 Edge &e = E[k];
5.7 Eertree . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
d[e.v] = d[e.u] + 1;
q.emplace(e.v);
6 Data structures 17 }
6.1 BIT Range Queries . . . . . . . . . . . . . . . . . . . . . 17 }
6.2 Treaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 }
6.3 Link-Cut Tree . . . . . . . . . . . . . . . . . . . . . . . . 18 return d[T] != N + 1;
}
long long DFS(int u, int T, long long flow = -1) {
7 Miscellaneous 19 if (u == T || flow == 0) return flow;
2
IIIT-Delhi - Cogito Ergo Error

for (int &i = pt[u]; i < g[u].size(); ++i) { Edge &back = G[e.to][e.rev];
Edge &e = E[g[u][i]]; if (!ex[e.to] && f)
Edge &oe = E[g[u][i]^1]; hs[h[e.to]].push_back(e.to);
if (d[e.v] == d[e.u] + 1) { e.f -= f; ex[e.to] += f;
long long amt = e.cap - e.flow; back.f += f; ex[back.to] -= f;
if (flow != -1 && amt > flow) amt = flow; }
if (long long pushed = DFS(e.v, T, amt)) { vector<vector<int> > hs;
e.flow += pushed; vector<int> co;
oe.flow -= pushed; flow_t max_flow() {
return pushed; ex.assign(N, 0);
} h.assign(N, 0); hs.resize(2*N);
} co.assign(2*N, 0); cur.assign(N, 0);
} h[S] = N;
return 0; ex[T] = 1;
} co[0] = N-1;
long long MaxFlow(int S, int T) { for(auto &e:G[S]) add_flow(e, e.f);
long long total = 0; if(hs[0].size())
while (BFS(S, T)) { for (int hi = 0;hi>=0;) {
fill(pt.begin(), pt.end(), 0); int u = hs[hi].back();
while (long long flow = DFS(S, T)) hs[hi].pop_back();
total += flow; while (ex[u] > 0) { // discharge u
} if (cur[u] == G[u].size()) {
return total; h[u] = 1e9;
} for(unsigned int i=0;i<G[u].size();++i){
}; auto &e = G[u][i];
if (e.f && h[u] > h[e.to]+1){
h[u] = h[e.to]+1, cur[u] = i;
1.2 Min-cost Circulation }
}
// Runs in O(<max_flow > * log(V * max_edge_cost)) = O( if (++co[h[u]], !--co[hi] && hi < N)
V^3 * // log(V * C)) Really fast in // practice , 3e4 for(int i=0;i<N;++i)
edges are fine. Operates on integers , // costs are if (hi < h[i] && h[i] < N){
multiplied by N!! --co[h[i]];
template<typename flow_t = int, typename cost_t = int> h[i] = N + 1;
struct mcSFlow{ }
struct Edge{ hi = h[u];
cost_t c; } else if (G[u][cur[u]].f && h[u] == h[G[u][cur[
flow_t f; u]].to]+1)
int to, rev; add_flow(G[u][cur[u]], min(ex[u], G[u][cur[u
Edge(int _to, cost_t _c, flow_t _f, int _rev):c(_c), ]].f));
f(_f), to(_to), rev(_rev){} else ++cur[u];
}; }
static constexpr cost_t INFCOST = numeric_limits< while (hi>=0 && hs[hi].empty()) --hi;
cost_t>::max()/2; }
cost_t eps; return -ex[S];
int N, S, T; }
vector<vector<Edge> > G; void push(Edge &e, flow_t amt){
vector<unsigned int> isq, cur; if(e.f < amt) amt=e.f;
vector<flow_t> ex; e.f-=amt; ex[e.to]+=amt;
vector<cost_t> h; G[e.to][e.rev].f+=amt; ex[G[e.to][e.rev].to]-=amt;
mcSFlow(int _N, int _S, int _T):eps(0), N(_N), S(_S), }
T(_T), G(_N){} void relabel(int vertex){
void add_edge(int a, int b, cost_t cost, flow_t cap){ cost_t newHeight = -INFCOST;
assert(cap>=0); for(unsigned int i=0;i<G[vertex].size();++i){
assert(a>=0&&a<N&&b>=0&&b<N); Edge const&e = G[vertex][i];
if(a==b){assert(cost>=0); return;} if(e.f && newHeight < h[e.to]-e.c){
cost*=N; newHeight = h[e.to] - e.c;
eps = max(eps, abs(cost)); cur[vertex] = i;
G[a].emplace_back(b, cost, cap, G[b].size()); }
G[b].emplace_back(a, -cost, 0, G[a].size()-1); }
} h[vertex] = newHeight - eps;
void add_flow(Edge& e, flow_t f) {
3
IIIT-Delhi - Cogito Ergo Error

}
static constexpr int scale=2;
pair<flow_t, cost_t> minCostMaxFlow(){
1.3 Edmonds Max Matching
cost_t retCost = 0; #define MAXN 505
for(int i=0;i<N;++i) vector<int>g[MAXN];
for(Edge &e:G[i]) int pa[MAXN],match[MAXN],st[MAXN],S[MAXN],v[MAXN];
retCost += e.c*(e.f); int t,n;
//find max-flow inline int lca(int x,int y){
flow_t retFlow = max_flow(); for(++t;;swap(x,y)) if(x){
h.assign(N, 0); ex.assign(N, 0); if(v[x]==t)return x;
isq.assign(N, 0); cur.assign(N,0); v[x]=t, x=st[pa[match[x]]];
queue<int> q; }
for(;eps;eps>>=scale){ }
//refine #define qpush(x) q.push(x),S[x]=0
fill(cur.begin(), cur.end(), 0); void flower(int x,int y,int l,queue<int> &q){
for(int i=0;i<N;++i) while(st[x]!=l){
for(auto &e:G[i]) pa[x]=y, y=match[x];
if(h[i] + e.c - h[e.to] < 0 && e.f) push(e, e. if(S[y]==1) qpush(y);
f); st[x]=st[y]=l, x=pa[y];
for(int i=0;i<N;++i){ }
if(ex[i]>0){ }
q.push(i); bool bfs(int x){
isq[i]=1; for(int i=1;i<=n;++i)st[i]=i;
} memset(S+1,-1,sizeof(int)*n);
} queue<int>q;
// make flow feasible qpush(x);
while(!q.empty()){ while(q.size()){
int u=q.front();q.pop(); x=q.front(),q.pop();
isq[u]=0; for(size_t i=0;i<g[x].size();++i){
while(ex[u]>0){ int y=g[x][i];
if(cur[u] == G[u].size()) if(S[y]==-1){
relabel(u); pa[y]=x, S[y]=1;
for(unsigned int &i=cur[u], max_i = G[u].size if(!match[y]){
();i<max_i;++i){ for(int lst;x;y=lst,x=pa[y]){
Edge &e=G[u][i];
if(h[u] + e.c - h[e.to] < 0){ lst=match[x], match[x]=y, match[y]=x;
push(e, ex[u]); }
if(ex[e.to]>0 && isq[e.to]==0){ return 1;
q.push(e.to); }
isq[e.to]=1; qpush(match[y]);
} } else if(!S[y]&&st[y]!=st[x]){
if(ex[u]==0) break; int l=lca(y,x);
} flower(y,x,l,q); flower(x,y,l,q);
} }
} }
} }
if(eps>1 && eps>>scale==0){ return 0;
eps = 1<<scale; }
} int blossom(){
} int ans=0;
for(int i=0;i<N;++i){ for(int i=1;i<=n;++i)
for(Edge &e:G[i]){ if(!match[i]&&bfs(i))++ans;
retCost -= e.c*(e.f); return ans;
} }
} int main(){
return make_pair(retFlow, retCost/2/N); while(m--){
} g[x].push_back(y);
flow_t getFlow(Edge const &e){ g[y].push_back(x);
return G[e.to][e.rev].f; }
} printf("%d\n",blossom());
}; for(int i=1;i<=n;i++)printf("%d ",match[i]);
}
4
IIIT-Delhi - Cogito Ergo Error

for (int k = 0; k < n; k++) {


1.4 Hungarian Min-cost if (seen[k]) continue;
const double new_dist = dist[j] + cost[i][k] - u
double MinCostMatching(const VVD &cost, VI &Lmate, VI & [i] - v[k];
Rmate) { if (dist[k] > new_dist) {
int n = int(cost.size()); dist[k] = new_dist;
// construct dual feasible solution dad[k] = j;
VD u(n); }
VD v(n); }
for (int i = 0; i < n; i++) { }
u[i] = cost[i][0]; // update dual variables
for (int j = 1; j < n; j++) u[i] = min(u[i], cost[i for (int k = 0; k < n; k++) {
][j]); if (k == j || !seen[k]) continue;
} const int i = Rmate[k];
for (int j = 0; j < n; j++) { v[k] += dist[k] - dist[j];
v[j] = cost[0][j] - u[0]; u[i] -= dist[k] - dist[j];
for (int i = 1; i < n; i++) v[j] = min(v[j], cost[i }
][j] - u[i]); u[s] += dist[j];
} // augment along path
// construct primal solution satisfying complementary
slackness while (dad[j] >= 0) {
Lmate = VI(n, -1); const int d = dad[j];
Rmate = VI(n, -1); Rmate[j] = Rmate[d];
int mated = 0; Lmate[Rmate[j]] = j;
for (int i = 0; i < n; i++) { j = d;
for (int j = 0; j < n; j++) { }
if (Rmate[j] != -1) continue; Rmate[j] = s;
if (fabs(cost[i][j] - u[i] - v[j]) < 1e-10) { Lmate[s] = j;
Lmate[i] = j; mated++;
Rmate[j] = i; }
mated++; double value = 0;
break; for (int i = 0; i < n; i++)
} value += cost[i][Lmate[i]];
} return value;
} }
VD dist(n);
VI dad(n); 1.5 Konig’s Theorem (Text)
VI seen(n); In any bipartite graph, the number of edges in a maximum matching equals
// repeat until primal solution is feasible
while (mated < n) { the number of vertices in a minimum vertex cover. To exhibit the vertex
// find an unmatched left node cover:
int s = 0; 1. Find a maximum matching
while (Lmate[s] != -1) s++; 2. Change each edge used in the matching into a directed edge from
// initialize Dijkstra right to left
fill(dad.begin(), dad.end(), -1); 3. Change each edge not used in the matching into a directed edge from
fill(seen.begin(), seen.end(), 0);
for (int k = 0; k < n; k++) left to right
dist[k] = cost[s][k] - u[s] - v[k]; 4. Compute the set 𝑇 of all vertices reachable from unmatched vertices
int j = 0; on the left (including themselves)
while (true) { 5. The vertex cover consists of all vertices on the right that are in 𝑇, and
// find closest
j = -1; all vertices on the left that are not in 𝑇
for (int k = 0; k < n; k++) {
if (seen[k]) continue;
if (j == -1 || dist[k] < dist[j]) j = k;
} 1.6 Minimum Edge Cover (Text)
seen[j] = 1; If a minimum edge cover contains 𝐶 edges, and a maximum matching con-
// termination condition tains 𝑀 edges, then 𝐶 + 𝑀 = |𝑉 |. To obtain the edge cover, start with
if (Rmate[j] == -1) break;
// relax neighbors a maximum matching, and then, for every vertex not matched, just select
const int i = Rmate[j]; some edge incident upon it and add it to the edge set.
5
IIIT-Delhi - Cogito Ergo Error

2 Geometry
// determine if lines from a to b and c to d are
2.1 Miscellaneous geometry parallel or collinear
bool LinesParallel(PT a, PT b, PT c, PT d) {
double INF = 1e100,EPS = 1e-12; return fabs(cross(b-a, c-d)) < EPS;
}
struct PT {
double x, y; bool LinesCollinear(PT a, PT b, PT c, PT d) {
PT() {} return LinesParallel(a, b, c, d)
PT(double x, double y) : x(x), y(y) {} && fabs(cross(a-b, a-c)) < EPS
PT(const PT &p) : x(p.x), y(p.y) {} && fabs(cross(c-d, c-a)) < EPS;
PT operator + (const PT &p) const { return PT(x+p.x, }
y+p.y); } // determine if line segment from a to b intersects with
PT operator - (const PT &p) const { return PT(x-p.x, // line segment from c to d
y-p.y); } bool SegmentsIntersect(PT a, PT b, PT c, PT d) {
PT operator * (double c) const { return PT(x*c, if (LinesCollinear(a, b, c, d)) {
y*c ); }
PT operator / (double c) const { return PT(x/c, if (dist2(a, c) < EPS || dist2(a, d) < EPS ||
y/c ); } dist2(b, c) < EPS || dist2(b, d) < EPS) return
}; true;
if (dot(c-a, c-b) > 0 && dot(d-a, d-b) > 0 && dot(c-
double dot(PT p, PT q) { return p.x*q.x+p.y*q.y; } b, d-b) > 0)
double dist2(PT p, PT q) { return dot(p-q,p-q); } return false;
double cross(PT p, PT q) { return p.x*q.y-p.y*q.x; } return true;
ostream &operator<<(ostream &os, const PT &p) { }
os << "(" << p.x << "," << p.y << ")"; if (cross(d-a, b-a) * cross(c-a, b-a) > 0) return
} false;
// rotate a point CCW or CW around the origin if (cross(a-c, d-c) * cross(b-c, d-c) > 0) return
PT RotateCCW90(PT p) { return PT(-p.y,p.x); } false;
PT RotateCW90(PT p) { return PT(p.y,-p.x); } return true;
PT RotateCCW(PT p, double t) { }
return PT(p.x*cos(t)-p.y*sin(t), p.x*sin(t)+p.y*cos(t) // compute intersection of line passing through a and b
); // with line passing through c and d, assuming that
} unique
// project point c onto line through a and b // intersection exists; for segment intersection, check
// assuming a != b if
PT ProjectPointLine(PT a, PT b, PT c) { // segments intersect first
return a + (b-a)*dot(c-a, b-a)/dot(b-a, b-a); PT ComputeLineIntersection(PT a, PT b, PT c, PT d) {
} b=b-a; d=c-d; c=c-a;
assert(dot(b, b) > EPS && dot(d, d) > EPS);
// project point c onto line segment through a and b return a + b*cross(c, d)/cross(b, d);
PT ProjectPointSegment(PT a, PT b, PT c) { }
double r = dot(b-a,b-a);
if (fabs(r) < EPS) return a; // compute center of circle given three points
r = dot(c-a, b-a)/r; PT ComputeCircleCenter(PT a, PT b, PT c) {
if (r < 0) return a; b=(a+b)/2;
if (r > 1) return b; c=(a+c)/2;
return a + (b-a)*r; return ComputeLineIntersection(b, b+RotateCW90(a-b), c
} , c+RotateCW90(a-c));
}
// compute distance from c to segment between a and b // determine if point is in a possibly non-convex
double DistancePointSegment(PT a, PT b, PT c) { polygon (by William
return sqrt(dist2(c, ProjectPointSegment(a, b, c))); // Randolph Franklin); returns 1 for strictly interior
} points, 0 for
// compute distance between point (x,y,z) and plane ax+ // strictly exterior points, and 0 or 1 for the
by+cz=d remaining points.
double DistancePointPlane(double x, double y, double z, // Note that it is possible to convert this into an *
double a, double b, double c, exact* test using
double d) // integer arithmetic by taking care of the division
{ appropriately
return fabs(a*x+b*y+c*z-d)/sqrt(a*a+b*b+c*c); // (making sure to deal with signs properly) and then by
} writing exact
6
IIIT-Delhi - Cogito Ergo Error

// tests for checking point on polygon boundary // counterclockwise fashion. Note that the centroid is
bool PointInPolygon(const vector<PT> &p, PT q) { often known as
bool c = 0; // the "center of gravity" or "center of mass".
for (int i = 0; i < p.size(); i++){ double ComputeSignedArea(const vector<PT> &p) {
int j = (i+1)%p.size(); double area = 0;
if ((p[i].y <= q.y && q.y < p[j].y || for(int i = 0; i < p.size(); i++) {
p[j].y <= q.y && q.y < p[i].y) && int j = (i+1) % p.size();
q.x < p[i].x + (p[j].x - p[i].x) * (q.y - p[i].y) area += p[i].x*p[j].y - p[j].x*p[i].y;
/ (p[j].y - p[i].y)) }
c = !c; return area / 2.0;
} }
return c; double ComputeArea(const vector<PT> &p) {
} return fabs(ComputeSignedArea(p));
// determine if point is on the boundary of a polygon }
bool PointOnPolygon(const vector<PT> &p, PT q) { PT ComputeCentroid(const vector<PT> &p) {
for (int i = 0; i < p.size(); i++) PT c(0,0);
if (dist2(ProjectPointSegment(p[i], p[(i+1)%p.size() double scale = 6.0 * ComputeSignedArea(p);
], q), q) < EPS) for (int i = 0; i < p.size(); i++){
return true;
return false; int j = (i+1) % p.size();
} c = c + (p[i]+p[j])*(p[i].x*p[j].y - p[j].x*p[i].y);
}
// compute intersection of line through points a and b return c / scale;
with }
// circle centered at c with radius r > 0
vector<PT> CircleLineIntersection(PT a, PT b, PT c, // tests whether or not a given polygon (in CW or CCW
double r) { order) is simple
vector<PT> ret; bool IsSimple(const vector<PT> &p) {
b = b-a; for (int i = 0; i < p.size(); i++) {
a = a-c; for (int k = i+1; k < p.size(); k++) {
double A = dot(b, b); int j = (i+1) % p.size();
double B = dot(a, b); int l = (k+1) % p.size();
double C = dot(a, a) - r*r; if (i == l || j == k) continue;
double D = B*B - A*C; if (SegmentsIntersect(p[i], p[j], p[k], p[l]))
if (D < -EPS) return ret; return false;
ret.push_back(c+a+b*(-B+sqrt(D+EPS))/A); }
if (D > EPS) }
ret.push_back(c+a+b*(-B-sqrt(D))/A); return true;
return ret; }
}
// compute intersection of circle centered at a with
radius r 2.2 3D geometry
// with circle centered at b with radius R
vector<PT> CircleCircleIntersection(PT a, PT b, double r public class Geom3D {
, double R) { // distance from point (x, y, z) to plane aX + bY + cZ
vector<PT> ret; + d = 0
double d = sqrt(dist2(a, b)); public static double ptPlaneDist(double x, double y,
if (d > r+R || d+min(r, R) < max(r, R)) return ret; double z,
double x = (d*d-R*R+r*r)/(2*d); double a, double b, double c, double d) {
double y = sqrt(r*r-x*x); return Math.abs(a*x + b*y + c*z + d) / Math.sqrt(a*a
PT v = (b-a)/d; + b*b + c*c);
ret.push_back(a+v*x + RotateCCW90(v)*y); }
if (y > 0) // distance between parallel planes aX + bY + cZ + d1
ret.push_back(a+v*x - RotateCCW90(v)*y); = 0 and
return ret; // aX + bY + cZ + d2 = 0
} public static double planePlaneDist(double a, double b
// This code computes the area or centroid of a ( , double c,
possibly nonconvex) double d1, double d2) {
// polygon, assuming that the coordinates are listed in return Math.abs(d1 - d2) / Math.sqrt(a*a + b*b + c*c
a clockwise or );
}
7
IIIT-Delhi - Cogito Ergo Error

// distance from point (px, py, pz) to line (x1, y1, return sqrt(pow(a.first-b.first,2)+pow(a.second-b.
z1)-(x2, y2, z2) second,2));
// (or ray, or segment; in the case of the ray, the }
endpoint is the vector<PT> convexhull(vector<PT> a){
// first point) vector<PT> hull;
public static final int LINE = 0; sort(a.begin(),a.end(),[](PT i, PT j){
public static final int SEGMENT = 1; if(i.second!=j.second)
public static final int RAY = 2; return i.second < j.second;
public static double ptLineDistSq(double x1, double y1 return i.first < j.first;
, double z1, });
double x2, double y2, double z2, double px, double for(int i=0;i<a.size();++i){
py, double pz, while(hull.size()>1 && cross(hull[hull.size()-2],
int type) { hull.back(),a[i])<=0)
double pd2 = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1 hull.pop_back();
-z2)*(z1-z2); hull.push_back(a[i]);
}
double x, y, z; for(int i=a.size()-1, siz = hull.size();i--;){
if (pd2 == 0) { while(hull.size()>siz && cross(hull[hull.size()-2],
x = x1; hull.back(),a[i])<=0)
y = y1; hull.pop_back();
z = z1; hull.push_back(a[i]);
} else { }
double u = ((px-x1)*(x2-x1) + (py-y1)*(y2-y1) + ( return hull;
pz-z1)*(z2-z1)) / pd2; }
x = x1 + u * (x2 - x1);
y = y1 + u * (y2 - y1);
z = z1 + u * (z2 - z1);
if (type != LINE && u < 0) {
2.4 Min Enclosing Circle
x = x1; // Minimum enclosing circle, Welzl’s algorithm
y = y1; // Expected linear time.
z = z1; // If there are any duplicate points in the input, be
} sure to remove them first.
if (type == SEGMENT && u > 1.0) { struct point {
x = x2; double x;
y = y2; double y;
z = z2; };
} struct circle {
} double x;
return (x-px)*(x-px) + (y-py)*(y-py) + (z-pz)*(z-pz) double y;
; double r;
} circle() {}
circle(double x, double y, double r): x(x), y(y)
public static double ptLineDist(double x1, double y1, , r(r) {}
double z1, };
double x2, double y2, double z2, double px, double circle b_md(vector<point> R) {
py, double pz, if (R.size() == 0) {
int type) { return circle(0, 0, -1);
return Math.sqrt(ptLineDistSq(x1, y1, z1, x2, y2, z2 } else if (R.size() == 1) {
, px, py, pz, type)); return circle(R[0].x, R[0].y, 0);
} } else if (R.size() == 2) {
} return circle((R[0].x+R[1].x)/2.0,
(R[0].y+R[1].y)/2.0,
hypot(R[0].x-R
2.3 Convex hull [1].x, R
[0].y-R[1].
typedef pair<long long, long long> PT; y)/2.0);
inline long long cross(PT o, PT a, PT b){ } else {
PT OA = {a.first-o.first,a.second-o.second}; double D = (R[0].x - R[2].x)*(R[1].y - R
PT OB = {b.first-o.first,b.second-o.second}; [2].y) - (R[1].x - R[2].x)*(R[0].y -
return OA.first*OB.second - OA.second*OB.first; R[2].y);
} double p0 = (((R[0].x - R[2].x)*(R[0].x
inline long double dist(PT a, PT b){ + R[2].x) + (R[0].y - R[2].y)*(R[0].y
8
IIIT-Delhi - Cogito Ergo Error

+ R[2].y)) / 2 * (R[1].y - R[2].y) - vector<triple> delaunayTriangulation(vector<T>& x,


((R[1].x - R[2].x)*(R[1].x + R[2].x) vector<T>& y) {
+ (R[1].y - R[2].y)*(R[1].y + R[2].y int n = x.size();
)) / 2 * (R[0].y - R[2].y))/D; vector<T> z(n);
double p1 = (((R[1].x - R[2].x)*(R[1].x vector<triple> ret;
+ R[2].x) + (R[1].y - R[2].y)*(R[1].y for (int i = 0; i < n; i++)
+ R[2].y)) / 2 * (R[0].x - R[2].x) - z[i] = x[i] * x[i] + y[i] * y[i];
((R[0].x - R[2].x)*(R[0].x + R[2].x) for (int i = 0; i < n-2; i++) {
+ (R[0].y - R[2].y)*(R[0].y + R[2].y for (int j = i+1; j < n; j++) {
)) / 2 * (R[1].x - R[2].x))/D; for (int k = i+1; k < n; k++) {
return circle(p0, p1, hypot(R[0].x - p0, if (j == k) continue;
R[0].y - p1)); double xn = (y[j]-y[i])*(z[k]-z[i]) - (y[k]-y[i
} ])*(z[j]-z[i]);
} double yn = (x[k]-x[i])*(z[j]-z[i]) - (x[j]-x[i
circle b_minidisk(vector<point>& P, int i, vector<point> ])*(z[k]-z[i]);
R) { double zn = (x[j]-x[i])*(y[k]-y[i]) - (x[k]-x[i
if (i == P.size() || R.size() == 3) { ])*(y[j]-y[i]);
return b_md(R); bool flag = zn < 0;
} else { for (int m = 0; flag && m < n; m++)
circle D = b_minidisk(P, i+1, R); flag = flag && ((x[m]-x[i])*xn + (y[m]-y[i])*
if (hypot(P[i].x-D.x, P[i].y-D.y) > D.r) yn + (z[m]-z[i])*zn <= 0);
{ if (flag) ret.push_back(triple(i, j, k));
R.push_back(P[i]); }
D = b_minidisk(P, i+1, R); }
} }
return D; return ret;
} }
}
int main(){
// Call this function. T xs[]={0, 0, 1, 0.9};
circle minidisk(vector<point> P) { T ys[]={0, 1, 0, 0.9};
random_shuffle(P.begin(), P.end()); vector<T> x(&xs[0], &xs[4]), y(&ys[0], &ys[4]);
return b_minidisk(P, 0, vector<point>()); vector<triple> tri = delaunayTriangulation(x, y);
} //expected: 0 1 3
// 0 3 2
for(int i = 0; i < tri.size(); i++)
2.5 Pick’s Theorem (Text) printf("%d %d %d\n", tri[i].i, tri[i].j, tri[i].k);
For a polygon with all vertices on lattice points, 𝐴 = 𝑖 + 𝑏/2 − 1, where }
𝐴kon is the area, 𝑖 is the number of lattice points strictly within the polygon,
and 𝑏 is the number of lattice points on the boundary of the polygon. (Note,3 Numerical algorithms
there is no generalization to higher dimensions)
3.1 Pollard Rho
typedef long long unsigned int llui;
2.6 Slow Delaunay triangulation typedef long long int lli;
typedef long double float64;
// Slow but simple Delaunay triangulation. Does not
// handle degenerate cases (from O’Rourke) llui mul_mod(llui a, llui b, llui m){
// llui y = (llui)((float64)a*(float64)b/m+(float64)1/2);
y = y * m;
// Running time: O(n^4) llui x = a * b;
// INPUT: x[] = x-coordinates llui r = x - y;
// y[] = y-coordinates if ( (lli)r < 0 ){
// OUTPUT: triples = a vector containing m triples of r = r + m; y = y - 1;
// indices corresponding to triangle vertices }
typedef double T; return r;
}
struct triple { llui C,a,b;
int i, j, k; llui gcd(){
triple() {} llui c;
triple(int i, int j, int k) : i(i), j(j), k(k) {} if(a>b){
}; c = a; a = b; b = c;
9
IIIT-Delhi - Cogito Ergo Error

} if(x != n-1) return false;


while(1){ }
if(a == 1LL) return 1LL; return true;
if(a == 0 || a == b) return b; }
c = a; a = b%a; map<llui,int> factors;
b = c; // Precondition: factors is an empty map, n is a
} positive integer
} // Postcondition: factors[p] is the exponent of p in
llui f(llui a, llui b){ prime factorization of n
llui tmp; void fact(llui n){
tmp = mul_mod(a,a,b); if(!isPrime(n)){
tmp+=C; tmp%=b; llui fac = pollard(n);
return tmp; fact(n/fac); fact(fac);
} }else{
llui pollard(llui n){ map<llui,int>::iterator it;
if(!(n&1)) return 2; it = factors.find(n);
C=0; if(it != factors.end()){
llui iteracoes = 0; (*it).second++;
while(iteracoes <= 1000){ }else{
llui x,y,d; factors[n] = 1;
x = y = 2; d = 1; }
while(d == 1){ }
x = f(x,n); }
y = f(f(y,n),n);
llui m = (x>y)?(x-y):(y-x);
a = m; b = n; d = gcd(); 3.2 Simplex algorithm
}
if(d != n) // Two-phase simplex algorithm for solving linear
return d; programs of the form
iteracoes++; C = rand(); // maximize c^T x
} // subject to Ax <= b ; x >= 0
return 1; // INPUT: A -- an m x n matrix
} // b -- an m-dimensional vector
llui pot(llui a, llui b, llui c){ // c -- an n-dimensional vector
if(b == 0) return 1; // x -- a vector where the optimal solution will
if(b == 1) return a%c; be stored
llui resp = pot(a,b>>1,c); // OUTPUT: value of the optimal solution (infinity if
resp = mul_mod(resp,resp,c); // unbounded above, nan if infeasible)
if(b&1) // To use this code, create an LPSolver object with
resp = mul_mod(resp,a,c); // A, b, and c as arguments. Then, call Solve(x).
return resp; typedef long double DOUBLE;
} typedef vector<DOUBLE> VD;
// Rabin-Miller primality testing algorithm typedef vector<VD> VVD;
bool isPrime(llui n){ typedef vector<int> VI;
llui d = n-1; const DOUBLE EPS = 1e-9;
llui s = 0; struct LPSolver {
if(n <=3 || n == 5) return true; int m, n;
if(!(n&1)) return false; VI B, N;
VVD D;
while(!(d&1)){ s++; d>>=1; } LPSolver(const VVD &A, const VD &b, const VD &c) :
for(llui i = 0;i<32;i++){ m(b.size()), n(c.size()), N(n + 1), B(m), D(m + 2,
llui a = rand(); VD(n + 2)) {
a <<=32; for (int i = 0; i < m; i++) for (int j = 0; j < n; j
a+=rand(); ++) D[i][j] = A[i][j];
a%=(n-3); a+=2; for (int i = 0; i < m; i++) { B[i] = n + i; D[i][n]
llui x = pot(a,d,n); = -1; D[i][n + 1] = b[i]; }
if(x == 1 || x == n-1) continue; for (int j = 0; j < n; j++) { N[j] = j; D[m][j] = -c
for(llui j = 1;j<= s-1;j++){ [j]; }
x = mul_mod(x,x,n); N[n] = -1; D[m + 1][n] = 1;
if(x == 1) return false; }
if(x == n-1)break; void Pivot(int r, int s) {
} double inv = 1.0 / D[r][s];
10
IIIT-Delhi - Cogito Ergo Error

for (int i = 0; i < m + 2; i++) if (i != r) { -1, -5, 0 },


for (int j = 0; j < n + 2; j++) if (j != s) { 1, 5, 1 },
D[i][j] -= D[r][j] * D[i][s] * inv; { -1, -5, -1 }
for (int j = 0; j < n + 2; j++) if (j != s) D[r][j] };
*= inv; DOUBLE _b[m] = { 10, -4, 5, -5 }, _c[n] = { 1, -1, 0
for (int i = 0; i < m + 2; i++) if (i != r) D[i][s] };
*= -inv; VVD A(m);
D[r][s] = inv; VD b(_b, _b + m), c(_c, _c + n);
swap(B[r], N[s]); for (int i = 0; i < m; i++) A[i] = VD(_A[i], _A[i] + n
} );
bool Simplex(int phase) { LPSolver solver(A, b, c);
int x = phase == 1 ? m + 1 : m; VD x;
while (true) { DOUBLE value = solver.Solve(x);
int s = -1; cerr << "VALUE: " << value << endl; // VALUE: 1.29032
for (int j = 0; j <= n; j++) { cerr << "SOLUTION:"; // SOLUTION: 1.74194 0.451613 1
if (phase == 2 && N[j] == -1) continue; for (size_t i = 0; i < x.size(); i++) cerr << " " << x
if (s == -1 || D[x][j] < D[x][s] || D[x][j] == D [i];
}
[x][s] && N[j] < N[s]) s = j;
}
if (D[x][s] > -EPS) return true; 3.3 Reduced row echelon form
int r = -1; // Reduced row echelon form via Gauss-Jordan elimination
for (int i = 0; i < m; i++) { // with partial pivoting. This can be used for
if (D[i][s] < EPS) continue; // computing the rank of a matrix.
if (r == -1 || D[i][n + 1] / D[i][s] < D[r][n + // Running time: O(n^3)
1] / D[r][s] || // INPUT: a[][] = an nxm matrix
(D[i][n + 1] / D[i][s]) == (D[r][n + 1] / D[r // OUTPUT: rref[][] = an nxm matrix (stored in a[][])
][s]) && B[i] < B[r]) r = i; // returns rank of a[][]
} const double EPSILON = 1e-10;
if (r == -1) return false; typedef double T;
Pivot(r, s); typedef vector<T> VT;
} typedef vector<VT> VVT;
} int rref(VVT &a) {
DOUBLE Solve(VD &x) { int n = a.size(), m = a[0].size(), r = 0;
int r = 0; for (int c = 0; c < m && r < n; c++) {
for (int i = 1; i < m; i++) if (D[i][n + 1] < D[r][n int j = r;
+ 1]) r = i; for (int i = r + 1; i < n; i++)
if (D[r][n + 1] < -EPS) { if (fabs(a[i][c]) > fabs(a[j][c])) j = i;
Pivot(r, n); if (fabs(a[j][c]) < EPSILON) continue;
if (!Simplex(1) || D[m + 1][n + 1] < -EPS) return swap(a[j], a[r]);
-numeric_limits<DOUBLE>::infinity();
for (int i = 0; i < m; i++) if (B[i] == -1) { T s = 1.0 / a[r][c];
int s = -1; for (int j = 0; j < m; j++) a[r][j] *= s;
for (int j = 0; j <= n; j++) for (int i = 0; i < n; i++) if (i != r) {
if (s == -1 || D[i][j] < D[i][s] || D[i][j] == T t = a[i][c];
D[i][s] && N[j] < N[s]) s = j; for (int j = 0; j < m; j++) a[i][j] -= t * a[r][j
Pivot(i, s); ];
} }
r++;
} }
if (!Simplex(2)) return numeric_limits<DOUBLE>:: return r;
infinity(); }
x = VD(n);
for (int i = 0; i < m; i++) if (B[i] < n) x[B[i]] =
D[i][n + 1]; 3.4 Fast Fourier transform
return D[m][n + 1]; template<typename fpt>
} struct fft_wrap {
}; using cpx_t = complex<fpt>;
int main() { const fpt two_pi = 4 * acosl(0);
const int m = 4, n = 3;
DOUBLE _A[m][n] = { vector<cpx_t> roots; //stores the N-th roots of unity.
{ 6, -1, 0 }, int N;
11
IIIT-Delhi - Cogito Ergo Error

fft_wrap(int N) : roots(N), N(N) { fft_wrap(int _N) : roots(_N), N(_N) {


for (int i = 0; i < N; ++i) { roots[0] = 1;
roots[i] = EXP(two_pi * i / fpt(N)); for (int i = 1; i < N; ++i) {
} roots[i] = roots[i - 1] * gen;
} if (i != N - 1) {
cpx_t EXP(fpt theta) { assert(roots[i].v != 1);
return {cos(theta), sin(theta)}; }
} }
}
void fft(cpx_t *in, cpx_t *out, int size, int dir){ void fft(fpt *in, fpt *out, int size, int dir) {
bit_reverse(in, out, size); bit_reverse(in, out, size);
for (int s = 0; (1 << s) < size; ++s) { for (int s = 0; (1 << s) < size; ++s) {
int s_ = s + 1; int s_ = s + 1;
for (int k = 0; k < size; k += (1 << s_)) { for (int k = 0; k < size; k += (1 << s_)) {
for (int j = 0; j < (1 << s); ++j) { for (int j = 0; j < (1 << s); ++j) {
int id = (N + dir * (N >> s_) * j) & (N - 1); int id = (N + dir * (N >> s_) * j) & (N - 1);
cpx_t w = roots[id]; fpt w = roots[id];
cpx_t t = w * out[k + j + (1 << s)]; fpt t = w * out[k + j + (1 << s)];
cpx_t u = out[k + j]; fpt u = out[k + j];
out[k + j] = u + t; out[k + j] = u + t;
out[k + j + (1 << s)] = u - t; out[k + j + (1 << s)] = u - t;
} }
} }
} }
} }
void bit_reverse(fpt *in, fpt *out, int size) {
void bit_reverse(cpx_t *in, cpx_t *out, int size){ for (int i = 0; i < size; ++i) {
for (int i = 0; i < size; ++i) { int rev = 0, i_copy = i;
int rev = 0, i_copy = i; for (int j = 0; (1 << j) < size; ++j) {
for (int j = 0; (1 << j) < size; ++j) { rev = (rev << 1) + (i_copy & 1);
rev = (rev << 1) + (i_copy & 1); i_copy >>= 1;
i_copy >>= 1; }
} out[rev] = in[i];
out[rev] = in[i]; }
} }
} };
};
using fpt = field_t<mod>;
int main(){ fft_wrap<fpt, gen> fft_wrapper(1 << 18);
typedef complex<double> cpx_t;
fft_wrap<double> fft_wrapper(2048); vector<fpt> polymul(vector<fpt> P1, vector<fpt> P2) {
int fsize = P1.size() + P2.size() - 1;
vector<cpx_t> in = {1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, int N = max(P1.size(), P2.size());
0.0}, out(8); while(N & (N - 1)) {
fft_wrapper.fft(&in[0], &out[0], 8, 1); ++N;
fft_wrapper.fft(&out[0], &in[0], 8, -1); }
for (int i = 0; i < 8; ++i) { N *= 2;
cout << in[i].real() << ’ ’ << in[i].imag() << endl; P1.resize(N); P2.resize(N);
} vector<fpt> temp(N);
} fft_wrapper.fft(&P1[0], &temp[0], N, 1);
fft_wrapper.fft(&P2[0], &P1[0], N, 1);
for (int i = 0; i < N; ++i) {
3.5 Number Theoretic transform }
P1[i] *= temp[i];
// gen should be 5^((p - 1) / fft_wrapper_size) fft_wrapper.fft(&P1[0], &temp[0], N, -1);
field_t<mod> inv(N);
template<int P> inv = inv.modexp(mod - 2);
struct field_t { ... }; for (int i = 0; i < N; ++i) {
template<typename fpt, int gen> temp[i] *= inv;
struct fft_wrap { }
vector<fpt> roots; //stores the N-th roots of unity. temp.resize(fsize);
int N; return temp;
12
IIIT-Delhi - Cogito Ergo Error

} // All algorithms described here work on nonnegative


integers.
int mod(int a, int b) {
3.6 Discrete Logarithm return ((a%b) + b) % b;
}
// Calculates x such that g^x % md == h int lcm(int a, int b) {
int baby_giant(int g, int h, int md){ return a / __gcd(a, b)*b;
unordered_map<int,int> mp; }
int sq = ceil(sqrtl(md)); int powermod(int a, int b, int m){
for(int i=0,now=1;i<sq;++i) return b?powermod(a*a%m,b/2,m)*(b%2?a:1)%m:1;
mp[now] = i, now = (long long) now*g % md; }
for(int i=0,jmp=power(g,md-1-sq);i<sq;++i){ // returns g = gcd(a, b); finds x, y such that d = ax +
if(mp.find(h)!=mp.end()) return i*sq+mp[h]; by
h = (long long) h*jmp % md; int extended_euclid(int a, int b, int &x, int &y) {
} int xx = y = 0;
return -1; int yy = x = 1;
} while (b) {
int q = a / b;
int t = b; b = a%b; a = t;
3.7 Mobius Inversion (Text) t = xx; xx = x - q*xx; x = t;
t = yy; yy = y - q*yy; y = t;
 0 𝑛 not squarefree }
𝜇(𝑛) = 1 𝑛 squarefree w/ even no. of prime factors return a;
1 𝑛 squarefree w/ odd no. of prime factors }
Note that 𝜇(𝑎)𝜇(𝑏)n = 𝜇(𝑎𝑏) for 𝑎, 𝑏 relatively prime // finds all solutions to ax = b (mod n)
VI modular_linear_equation_solver(int a, int b, int n) {
Also 𝑑|𝑛 𝜇(𝑑) = 01 otherwise
if 𝑛 = 1 int x, y;
Í
VI ret;
Í int g = extended_euclid(a, n, x, y);
Möbius
Í Inversion If 𝑔(𝑛) = 𝑑|𝑛 𝑓 (𝑑) for all 𝑛 ≥ 1, then if (!(b%g)) {
𝑓 (𝑛) = 𝑑|𝑛 𝜇(𝑑)𝑔(𝑛/𝑑) for all 𝑛 ≥ 1. x = mod(x*(b / g), n);
for (int i = 0; i < g; i++)
ret.push_back(mod(x + i*(n / g), n));
}
return ret;
3.8 Burnside Lemma (Text) }
The number of orbits of a set 𝑋 under the group action 𝐺 equals the average // computes b such that ab = 1 (mod n), returns -1 on
number of elements of 𝑋 fixed by the elements of 𝐺. failure
int mod_inverse(int a, int n) {
Here’s an example. Consider a square of 2𝑛 times 2𝑛 cells. How int x, y;
many ways are there to color it into 𝑋 colors, up to rotations and/or reflec- int g = extended_euclid(a, n, x, y);
tions? Here, the group has only 8 elements (rotations by 0, 90, 180 and if (g > 1) return -1;
return mod(x, n);
270 degrees, reflections over two diagonals, over a vertical line and over a }
horizontal line). Every coloring stays itself after rotating by 0 degrees, so // Chinese remainder theorem (special case): find z such
2 // that z % m1 = r1, z % m2 = r2.
that rotation has 𝑋 4𝑛 fixed points. Rotation by 180 degrees and reflections // Here, z is unique modulo M = lcm(m1, m2).
over a horizonal/vertical line split all cells in pairs that must be of the same // Return (z, M). On failure, M = -1.
color for a coloring to be unaffected by such rotation/reflection, thus there PII chinese_remainder_theorem(int m1, int r1, int m2,
2 int r2) {
exist 𝑋 2𝑛 such colorings for each of them. Rotations by 90 and 270 degrees int s, t;
2 int g = extended_euclid(m1, m2, s, t);
split cells in groups of four, thus yielding 𝑋 𝑛 fixed colorings. Reflec- if (r1%g != r2%g) return make_pair(0, -1);
tions over diagonals split cells into 2𝑛 groups of 1 (the diagonal itself) and return make_pair(mod(s*r2*m1 + t*r1*m2, m1*m2) / g, m1
2
2𝑛2 − 𝑛 groups of 2 (all remaining cells), thus yielding 𝑋 2𝑛 −𝑛+2𝑛 = 𝑋 2𝑛 +𝑛
2 *m2 / g);
}
2 2 2 2
unaffected colorings. So, the answer is (𝑋 4𝑛 + 3𝑋 2𝑛 + 2𝑋 𝑛 + 2𝑋 2𝑛 +𝑛 )/8. // Find z such that z % m[i] = r[i] for all i.
// The solution is unique modulo M = lcm_i (m[i]).
// Return (z, M). On failure, M = -1.
// We don’t require a[i]’s to be relatively prime.
3.9 Number Theory (Modular, CRT, Linear Diophantine) PII chinese_remainder_theorem(const VI &m,const VI &r){
13
IIIT-Delhi - Cogito Ergo Error

PII ret = make_pair(r[0], m[0]); enum {ADD,DEL,QUERY};


for (int i = 1; i < m.size(); i++) { struct Query {int type,x,y;};
ret = chinese_remainder_theorem(ret.second, ret. struct DynCon {
first, m[i], r[i]); vector<Query> q;
if (ret.second == -1) break; UnionFind dsu;
} vector<int> mt;
return ret; map<pair<int,int>,int> last;
} DynCon(int n):dsu(n){}
// computes x and y such that ax + by = c void add(int x, int y){
// returns whether the solution exists if(x>y) swap(x,y);
bool linear_diophantine(int a, int b, int c, int &x, int q.push_back((Query){ADD,x,y}),mt.push_back(-1);
&y) { last[make_pair(x,y)]=q.size()-1;
if (!a && !b) { }
if (c) return false; void remove(int x, int y){
x = 0; y = 0; if(x>y)swap(x,y);
return true; q.push_back((Query){DEL,x,y});
} int pr=last[make_pair(x,y)];
if (!a) { mt[pr]=q.size()-1;
if (c % b) return false; mt.push_back(pr);
x = 0; y = c / b; }
return true; void query(int x, int y){
} q.push_back((Query){QUERY,x,y});
if (!b) { mt.push_back(-1);
if (c % a) return false; }
x = c / a; y = 0; void process(){ // answers all queries in order
return true; if(!q.size()) return;
} for(int i=0;i<q.size();++i)
int g = __gcd(a, b); if(q[i].type==ADD&&mt[i]<0)
if (c % g) return false; mt[i]=q.size();
x = c / g * mod_inverse(a / g, b / g); go(0,q.size());
y = (c - a*x) / b; }
return true;
} void go(int l, int r){
if(l+1==r){
if(q[l].type==QUERY) // answer query using DSU
4 Graph algorithms puts(dsu.find(q[l].x)==dsu.find(q[l].y)? "YES":"
NO");
return;
4.1 Dynamic Connectivity }
struct UnionFind { int s=dsu.snap(),m=(l+r)/2;
int n,comp; for(int i=r-1;i>=m;--i)
vector<int> uf,si,c; if(mt[i]>=0&&mt[i]<l)
UnionFind(int n=0):n(n),comp(n),uf(n),si(n,1){ dsu.join(q[i].x,q[i].y);
for(int i=0;i<n;++i) go(l,m);
uf[i]=i; dsu.rollback(s);
} for(int i=m-1;i>=l;--i)if(mt[i]>=r)dsu.join(q[i].x,q
int find(int x){return x==uf[x]?x:find(uf[x]);} [i].y);
bool join(int x, int y){ go(m,r);
if((x=find(x))==(y=find(y))) return false; dsu.rollback(s);
if(si[x]<si[y]) swap(x,y); }
si[x]+=si[y];uf[y]=x;comp--; };
c.push_back(y);
}
return true; 4.2 Bridges
int snap(){return c.size();} // Finds bridges and cut vertices
void rollback(int snap){ //
while(c.size()>snap){ // Receives:
int x=c.back(); c.pop_back(); // N: number of vertices
si[uf[x]]-=si[x];uf[x]=x;comp++; // l: adjacency list
} //
} // Gives:
}; // vis, seen, par (used to find cut vertices)
14
IIIT-Delhi - Cogito Ergo Error

// ap - 1 if it is a cut vertex, 0 otherwise


// brid - vector of pairs containing the bridges // Call this to add an edge (0-based)
void add_edge(int v1, int v2) {
typedef pair<int, int> PII; adj[v1].push_back(v2);
int N; radj[v2].push_back(v1);
vector <int> l[MAX]; }
vector <PII> brid; void fill_forward(int x) {
int vis[MAX], seen[MAX], par[MAX], ap[MAX]; vis[x] = true;
int cnt, root; for (int i = 0; i < adj[x].size(); i++) {
if (!vis[adj[x][i]]) {
void dfs(int x){ fill_forward(adj[x][i]);
if(vis[x] != -1) }
return; }
vis[x] = seen[x] = cnt++; stk.push(x);
int adj = 0; }
for(int i = 0; i < (int)l[x].size(); i++){ void fill_backward(int x) {
int v = l[x][i]; vis[x] = false;
if(par[x] == v) group_num[x] = group_cnt;
continue; for (int i = 0; i < radj[x].size(); i++) {
if(vis[v] == -1){ if (vis[radj[x][i]]) {
adj++; fill_backward(radj[x][i]);
par[v] = x; }
dfs(v); }
seen[x] = min(seen[x], seen[v]); }
// Returns number of strongly connected components.
if(seen[v] >= vis[x] && x != root) // After this is called, group_num contains component
ap[x] = 1; assignments (0-based)
if(seen[v] == vis[v]) int get_scc() {
brid.push_back(make_pair(v, x)); for (int i = 0; i < V; i++) {
} if (!vis[i]) fill_forward(i);
else{ }
seen[x] = min(seen[x], vis[v]); group_cnt = 0;
seen[v] = min(seen[x], seen[v]); while (!stk.empty()) {
}
} if (vis[stk.top()]) {
if(x == root) ap[x] = (adj>1); fill_backward(stk.top());
} group_cnt++;
}
void bridges(){ stk.pop();
brid.clear(); }
for(int i = 0; i < N; i++){ return group_cnt;
vis[i] = seen[i] = par[i] = -1; }
ap[i] = 0; };
}
cnt = 0;
for(int i = 0; i < N; i++) 5 String Stuff
if(vis[i] == -1){
root = i; 5.1 Suffix Automaton
dfs(i); struct SuffixAutomaton {
} vector<map<char,int>> edges; // edges[i]: the labeled
} edges from node i
vector<int> link; // link[i] : the parent of i
4.3 Strongly connected components vector<int> length; // length[i]: length of longest
string in ith class
struct SCC { vector<int> cnt; // No. of times substring occurs
int V, group_cnt; int last; // index of equivalence class of whole
vector<vector<int> > adj, radj; string
vector<int> group_num, vis; SuffixAutomaton(string const& s) {
stack<int> stk; // add the initial node
// V = number of vertices edges.push_back(map<char,int>());
SCC(int V): V(V), group_cnt(0), group_num(V), vis(V), link.push_back(-1);
adj(V), radj(V) {} length.push_back(0);
15
IIIT-Delhi - Cogito Ergo Error

cnt.push_back(0); for(;--i;F[i]=F[i]==F[i-1]&&G[i]==G[i-1]&&S[i-1]<n-L
last = 0; );
for(p=B[*S]=0;++i<n;B[S[i]]=p=F[i]?p:i);
for(int i=0;i<s.size();i++) { for(fill_n(G,n,0);i--;F[i]=S[i]<L?-1:B[S[i]-L]);
// construct r for(iota(C,C+n,0);++i<n;~F[i]?G[i]=C[F[i]]++:0);
edges.push_back(map<char,int>()); for(copy_n(S,n,F);i--;F[i]<L?0:S[G[i]]=F[i]-L);
length.push_back(i+1); }
link.push_back(0); vector<int>res(S,S+n);
cnt.push_back(1); delete[] M;
int r = edges.size() - 1; return res;
// add edges to r and find p with link to q }
int p = last; vector<int> kasai(string &s, vector<int> &sa){
while(p >= 0 && !edges[p].count(s[i])){ int n = s.size();
edges[p][s[i]] = r; vector<int> lcp(n),inv(n);
p = link[p]; for(int i=0;i<n;++i) inv[sa[i]] = i;
} for(int i=0,k=0;i<n;++i){
if(p != -1) { if(k<0) k = 0;
int q = edges[p][s[i]]; if(inv[i]==n-1){ k=0; continue; }
if(length[p] + 1 == length[q]) { for(int j=sa[inv[i]+1];max(i,j)+k<n&&s[i+k]==s[j+k
// we do not have to split q, just set the ];++k);
correct suffix link lcp[inv[i]] = k--;
link[r] = q; }
} else { return lcp;
// we have to split, add q’ }
edges.push_back(edges[q]); // copy edges of q
length.push_back(length[p] + 1);
link.push_back(link[q]); // copy parent of q 5.3 Z Algorithm
cnt.push_back(0);
int qq = edges.size()-1; vector<int> compute_Z(string s) {
// add qq as the new parent of q and r int n = s.length();
link[q] = link[r] = qq; cnt[r] = 1; vector<int> z(n, 0);
// move short classes pointing to q to point z[0] = n;
to q’ for (int i = 1, l = 0, r = 0; i < n; ++i) {
while(p >= 0 && edges[p][s[i]] == q) { if (r >= i) {
edges[p][s[i]] = qq; z[i] = min(z[i - l], r - i + 1);
p = link[p]; }
} while (i+z[i] < n and s[i+z[i]] == s[z[i]]) {
} ++z[i];
} }
last = r; if (i + z[i] - 1 > r) {
} r = i + z[i] - 1;
l = i;
vector<int> ind(length.size()); }
iota(ind.begin(), ind.end(), 0); }
sort(ind.begin(), ind.end(), [&](int i, int j){ return z;
return length[i] > length[j]; }
});
for(auto i:ind) if(link[i] >= 0)
cnt[link[i]] += cnt[i]; 5.4 KMP
} vector<int> find_prefix(const vector<int> &P){
}; int M = P.size();
vector<int> pi(M);
5.2 Suffix array /* pi[i] <- largest prefix P[0..pi[i]] which is a
suffix of P[0..i]
vector<int> suffix_array(string &A){ * (but not equal to it) */
int n=A.size(),i=n, *M=new int[5*n]; pi[0] = -1;
int *B=M,*C=M+n,*F=M+2*n,*G=M+3*n,*S=M+4*n; for (int i = 1, k = -1; i < M; ++i) {
for(;i--;S[i]=n-i-1) B[i]=A[i]; while(k > -1 && P[k + 1] != P[i])
stable_sort(S,S+n,[&](int i,int j){return A[i]<A[j];}) k = pi[k];
; if (P[k + 1] == P[i]) ++k;
for(int L=1,p;L<n;L*=2){ pi[i] = k;
for(;++i<n;F[i]=B[S[i]],G[i]=B[S[i]+L/2]); }
16
IIIT-Delhi - Cogito Ergo Error

return pi; assert(0 <= a && a < 2*n);


} assert(0 <= b && b < 2*n);
int kmp_matcher(const vector<int> &T, const vector<int> // union with splicing is a bit faster than
&P){ // just path compression also guarantees p[i] <= i
int M = P.size(), N = T.size(); while(p[a] != p[b]){
vector<int> pi = find_prefix(P); if(p[a] < p[b]) swap(a, b);
int q = -1, matches = 0; if(p[a] == a){
for (int i = 0; i < N; ++i) { p[a] = b;
while(q > -1 && P[q + 1] != T[i]) return;
q = pi[q]; }
if (P[q + 1] == T[i]) ++q; int tmp = p[a];
if (q == M - 1) p[a] = p[b];
++matches, q = pi[q]; a = p[tmp];
} }
return matches; }
} int components(){
int ret = 0;
for(int i=0;i<(int)p.size();++i)
5.5 String Hashing if(p[i] == i) ++ret;
return ret;
struct hasher{ }
int hashes[MAXN+5]; // call this after adding all queries
int *pow, *inv; void compute(){
int mod; vector<int> p2(2*n);
int n; for(int l=m-1; l>=0; --l){
void init(string &str, int *p, int *i, int m){ const int s = 1<<l;
pow = p;
inv = i; for(int i=0; i<2*n; ++i) p2[i] = f(i);
mod = m; for(int i=0; i+s<2*n; ++i){
n = str.size(); const int j = p2[i];
int last = 0; if(j+s < 2*n) u(i+s, j+s);
for (int i = 0; i < n; i++){ }
int c = str[i] - ’a’ + 1; for(auto const&e:qs[l])
last = (last + 1ll*c*pow[i]) % mod; u(e.first, e.second);
hashes[i] = last; }
} // link point with mirror-image
} for(int i=0;i<n;++i)
int getHash(int l, int r){ u(i, 2*n-1 - i);
if (r >= n || l < 0) }
// force [l, r] to be a palindrome
return -1; void add_q(int l, int r){
int curr = hashes[r] - (l-1 >= 0 ? hashes[l-1] : 0); assert(0 <= l && l <= r && r < n);
curr = ((curr % mod) + mod) % mod; if(l==r) return;
curr = (1ll*curr*inv[l]) % mod; const int range = r-l+1;
return curr;
} const int k = __lg(range);
} A, B, C; qs[k].emplace_back(l, 2*n-1 - r);
}
int n, m;
5.6 Palindrome DSU vector<vector<pair<int, int> > > qs;
// given an unknown string s and Q ranges that vector<int> p;
// are know to be palindromes, this computes the };
characters
// that have to be equal in O(Q + n log n) 5.7 Eertree
struct Palindrome{ /*
Palindrome(){} Palindrome tree. Useful structure to deal with
Palindrome(int n_):n(n_), m(3+__lg(n)), qs(m), p(2*n){ palindromes in strings. O(N)
iota(p.begin(), p.end(), 0); This code counts no. of palindrome substrings of string.
} Based on problem 1750 from informatics.mccme.ru:
int f(int i){ http://informatics.mccme.ru/moodle/mod/statements/view.
return p[i] == i ? i : p[i] = f(p[i]); php?chapterid =1750
}
void u(int a, int b){ */
17
IIIT-Delhi - Cogito Ergo Error

const int MAXN = 105000; ans += tree[suff].num;


struct node { }
cout << ans << endl;
int next[26]; }
int len;
int sufflink;
};
int num; 6 Data structures
int len; 6.1 BIT Range Queries
char s[MAXN];
node tree[MAXN]; struct BIT {
int num; // node 1 - root with len -1, node 2
- root with len 0 int n;
int suff; // max suffix palindrome vector<int> slope;
long long ans; vector<int> intercept;
bool addLetter(int pos) { // BIT can be thought of as having entries f[1], ...,
int cur = suff, curlen = 0; f[n] which are 0-initialized
int let = s[pos] - ’a’; BIT(int n): n(n), slope(n+1), intercept(n+1) {}
while (true) { // returns f[1] + ... + f[idx-1]
curlen = tree[cur].len; // precondition idx <= n+1
if (pos - 1 - curlen >= 0 && s[pos - 1 - curlen]
== s[pos]) int query(int idx) {
break; int m = 0, b = 0;
cur = tree[cur].sufflink; for (int i = idx-1; i > 0; i -= i&-i) {
} m += slope[i];
if (tree[cur].next[let]) { b += intercept[i];
suff = tree[cur].next[let]; }
return false; return m*idx + b;
} }
num++;
suff = num; // adds amt to f[i] for i in [idx1, idx2)
tree[num].len = tree[cur].len + 2; // precondition 1 <= idx1 <= idx2 <= n+1 (you can’t
tree[cur].next[let] = num; update element 0)
if (tree[num].len == 1) { void update(int idx1, int idx2, int amt) {
tree[num].sufflink = 2; for (int i = idx1; i <= n; i += i&-i) {
tree[num].num = 1; slope[i] += amt;
return true; intercept[i] -= idx1*amt;
} }
while (true) { for (int i = idx2; i <= n; i += i&-i) {
cur = tree[cur].sufflink; slope[i] -= amt;
curlen = tree[cur].len; intercept[i] += idx2*amt;
if (pos - 1 - curlen >= 0 && s[pos - 1 - curlen] }
== s[pos]) { }
tree[num].sufflink = tree[cur].next[let]; };
break;
}
} 6.2 Treaps
tree[num].num = 1 + tree[tree[num].sufflink].num;
return true; typedef struct node{
} int prior,size;
void initTree() { int val;//value stored in the array
num = 2; suff = 2; int sum;//whatever info you want to maintain in
tree[1].len = -1; tree[1].sufflink = 1; segtree for each node
tree[2].len = 0; tree[2].sufflink = 1; int lazy;//whatever lazy update you want to do
} struct node *l,*r;
int main() { } node;
gets(s);
len = strlen(s) struct Treap {
initTree() typedef node* pnode;
for (int i = 0; i < len; i++) { int sz(pnode t){
addLetter(i); return t?t->size:0;
}
18
IIIT-Delhi - Cogito Ergo Error

void upd_sz(pnode t){ split(t,L,mid,l-1);


if(t)t->size=sz(t->l)+1+sz(t->r); split(mid,t,R,r-l);//note: r-l!!
} int ans = t->sum;
void lazy(pnode t){ merge(mid,L,t);
if(!t || !t->lazy)return; merge(t,mid,R);
t->val+=t->lazy;//operation of lazy return ans;
t->sum+=t->lazy*sz(t); }
if(t->l)t->l->lazy+=t->lazy;//propagate lazy void range_update(pnode t,int l,int r,int val){//[l,r]
if(t->r)t->r->lazy+=t->lazy; pnode L,mid,R;
t->lazy=0; split(t,L,mid,l-1);
} split(mid,t,R,r-l);//note: r-l!!
void reset(pnode t){ t->lazy+=val; //lazy_update
if(t)t->sum = t->val;//no need to reset lazy coz merge(mid,L,t);
when we call this lazy would itself be propagated merge(t,mid,R);
} }
void combine(pnode& t,pnode l,pnode r){//combining two };
ranges of segtree
if(!l || !r)return void(t = l?l:r); 6.3 Link-Cut Tree
t->sum = l->sum + r->sum;
} const int MXN = 100005, MEM = 100005;
void operation(pnode t){//operation of segtree struct Splay {
if(!t)return; static Splay nil, mem[MEM], *pmem;
reset(t);//reset the value of current node assuming Splay *ch[2], *f;
it now represents a single element of the array int val, rev, size;
lazy(t->l);lazy(t->r);//imp:propagate lazy before Splay (int _val=-1) : val(_val), rev(0), size(1)
combining t->l,t->r; { f = ch[0] = ch[1] = &nil; }
combine(t,t->l,t); bool isr()
combine(t,t,t->r); { return f->ch[0] != this && f->ch[1] != this; }
} int dir()
void split(pnode t,pnode &l,pnode &r,int pos,int add { return f->ch[0] == this ? 0 : 1; }
=0){ void setCh(Splay *c, int d){
if(!t)return void(l=r=NULL); ch[d] = c;
lazy(t); if (c != &nil) c->f = this;
int curr_pos = add + sz(t->l); pull();
if(curr_pos<=pos)//element at pos goes to left }
subtree(l) void push(){
split(t->r,t->r,r,pos,curr_pos+1),l=t; if( !rev ) return;
else swap(ch[0], ch[1]);
split(t->l,l,t->l,pos,add),r=t; if (ch[0] != &nil) ch[0]->rev ^= 1;
upd_sz(t); if (ch[1] != &nil) ch[1]->rev ^= 1;
operation(t); rev=0;
} }
void merge(pnode &t,pnode l,pnode r){ //l->leftarray,r void pull(){
->rightarray,t->resulting array size = ch[0]->size + ch[1]->size + 1;
lazy(l);lazy(r); if (ch[0] != &nil) ch[0]->f = this;
if(!l || !r) t = l?l:r; if (ch[1] != &nil) ch[1]->f = this;
else if(l->prior>r->prior)merge(l->r,l->r,r),t=l; }
else merge(r->l,l,r->l),t=r; } Splay::nil, Splay::mem[MEM], *Splay::pmem = Splay::mem
upd_sz(t); ;
operation(t); Splay *nil = &Splay::nil;
} void rotate(Splay *x){
pnode init(int val){ Splay *p = x->f;
pnode ret = (pnode)malloc(sizeof(node)); int d = x->dir();
ret->prior=rand();ret->size=1; if (!p->isr()) p->f->setCh(x, p->dir());
ret->val=val; else x->f = p->f;
ret->sum=val;ret->lazy=0; p->setCh(x->ch[!d], d); x->setCh(p, !d); p->pull
return ret; (); x->pull();
} }
int range_query(pnode t,int l,int r){//[l,r] vector<Splay*> splayVec;
pnode L,mid,R; void splay(Splay *x){
splayVec.clear();
19
IIIT-Delhi - Cogito Ergo Error

for(Splay *q=x;; q=q->f){ Two_Sat(int N_) : N(N_) { // create a formula over N


splayVec.push_back(q); variables (numbered 1 to N)
if (q->isr()) break; G.resize(2*N);
} }
reverse(begin(splayVec), end(splayVec)); int add_variable() {
for (auto it : splayVec) it->push(); G.emplace_back(); G.emplace_back();
while (!x->isr()) return N++;
if (x->f->isr()) rotate(x); }
else if (x->dir()==x->f->dir()) rotate(x->f),rotate( private:
x); // converts a signed variable index to its position in
else rotate(x),rotate(x); val[] and G[]
} int to_ind(int x) {
int id(Splay *x) { return x - Splay::mem + 1; } return 2*(abs(x)-1) + (x<0);
Splay* access(Splay *x){ }
Splay *q = nil; // Add a directed edge to the graph.
for (;x!=nil;x=x->f) {splay(x); x->setCh(q, 1); q = x; // You most likely do not want to call this yourself!
} void add_edge(int a, int b) {
return q; G[to_ind(a)].push_back(to_ind(b));
} }
void chroot(Splay *x){ int time() {
access(x); splay(x); x->rev ^= 1; x->push(); x->pull() return valid.size()-1;
; }
} bool dfs(int x) {
void link(Splay *x, Splay *y){ if(valid[abs(val[x])]) return val[x]>0;
access(x); splay(x); val[x] = time();
chroot(y); x->setCh(y, 1); val[x^1] = -time();
} for(int e:G[x])
void cut_p(Splay *y) { if(!dfs(e))
access(y); splay(y); y->push(); y->ch[0] = y->ch[0]->f return false;
= nil; return true;
} }
void cut(Splay *x, Splay *y){ public:
chroot(x); cut_p(y); // Add the or-clause: (a or b)
} void add_or(int a, int b) {
Splay* get_root(Splay *x) { add_edge(-a,b); add_edge(-b,a);
access(x); splay(x); }
for(; x->ch[0] != nil; x = x->ch[0]) x->push(); // Add the implication: a -> b
splay(x); return x; void add_implication(int a, int b) {
} add_or(-a, b);
bool conn(Splay *x, Splay *y) { }
return (x = get_root(x)) == (y = get_root(y)); // Add condition: x is true
} void add_true(int x) {
Splay* lca(Splay *x, Splay *y) { add_or(x,x);
access(x); access(y); splay(x); }
if (x->f == nil) return x; // At most one with linear number of clauses
else return x->f; template<typename T>
} void add_at_most_one(T vars) {
if(vars.begin() == vars.end()) return;
int last = *vars.begin(), cur = 0;
7 Miscellaneous for(int const&e:vars){
if(e == last) continue;
if(cur == 0) cur = e;
7.1 2-SAT else {
add_or(-cur, -e);
class Two_Sat { int new_cur = add_variable();
int N; // number of variables cur = add_implication(cur, new_cur);
vector<int> val; // assignment of x is at val[2x] and add_implication(e, new_cur);
-x at val[2x+1] cur = new_cur;
vector<char> valid; // changes made at time i are kept }
iff valid[i] }
vector<vector<int> > G; // graph of implications G[x][ if(cur != 0) add_or(-cur, -last);
i] = y means (x -> y)
20
IIIT-Delhi - Cogito Ergo Error

} return true;
bool solve() { }
val.assign(2*n, 0); valid.assign(1, 0);
for(int i=0; i<val.size(); i+=2) { public:
if(!valid[abs(val[i])]) { // Add the or-clause: (a or b)
valid.push_back(1); void add_or(int a, int b) {
if(!dfs(i)) { add_edge(-a,b);
valid.back()=0; add_edge(-b,a);
valid.push_back(1); }
if(!dfs(i+1)) return false; // Add the implication: a -> b
} void add_implication(int a, int b) {
} add_or(-a, b);
} }
return true;
} // Add condition: x is true
}; void add_true(int x) {
// Taken from https://github.com/dacin21/ add_or(x,x);
dacin21_codebook/blob/master/dfs_stuff/2sat.cpp }
// 2-sat in linear time via backtracking. // At most one with linear number of clauses
class Two_Sat { template<typename T>
int N; // number of variables void add_at_most_one(T vars) {
vector<int> val; // assignment of x is at val[2x] if(vars.begin() == vars.end()) return;
and -x at val[2x+1] int last = *vars.begin();
vector<char> valid; // changes made at time i are int cur = 0;
kept iff valid[i] for(int const&e:vars){
vector<vector<int> > G; // graph of implications G[x if(e == last) continue;
][i] = y means (x -> y) if(cur == 0) cur = e;
Two_Sat(int N_) : N(N_) { // create a formula over N else {
variables (numbered 1 to N) add_or(-cur, -e);
G.resize(2*N); int new_cur = add_variable();
} cur = add_implication(cur, new_cur);
add_implication(e, new_cur);
int add_variable() { cur = new_cur;
G.emplace_back(); }
G.emplace_back(); }
return N++; if(cur != 0){
} add_or(-cur, -last);
private: }
// converts a signed variable index to its position }
in val[] and G[] bool solve() {
int to_ind(int x) { val.assign(2*n, 0);
return 2*(abs(x)-1) + (x<0); valid.assign(1, 0);
} for(int i=0; i<val.size(); i+=2) {
// Add a directed edge to the graph. if(!valid[abs(val[i])]) {
// You most likely do not want to call this yourself valid.push_back(1);
! if(!dfs(i)) {
void add_edge(int a, int b) { valid.back()=0;
G[to_ind(a)].push_back(to_ind(b)); valid.push_back(1);
} if(!dfs(i+1)) return false;
}
int time() { }
return valid.size()-1; }
} return true;
}
bool dfs(int x) { };
if(valid[abs(val[x])]) return val[x]>0;
val[x] = time();
val[x^1] = -time();
for(int e:G[x])
7.2 Merge Insertion
if(!dfs(e)) // Sorting in O(n^2) time with near-optimal number of
return false; comparisons
21
IIIT-Delhi - Cogito Ergo Error

// Number of comparisons used is: n lg n - 1.415 n while(a+1 < b){


// The lower bound is: lg (n!) = n lg n - 1.443 n const int m = a+(b-a)/2;
// Binary search insertion sort would need: n log n - n if(comp(ret.first[m], v[i])) a = m;
struct Merge_Insertion_Sort{ else b = m;
template<typename F> }
static void apply_permutation(vector<int> const&p, F ret.first.insert(ret.first.begin()+b, v[i]);
get){ ret.second.insert(ret.second.begin()+b, i);
const int n = p.size(); }
vector<int> q(n); }
for(int i=0;i<n;++i) q[p[i]] = i; }
for(int i=0;i<n;++i){ // compose permutations
while(q[i] != i){ apply_permutation(ret.second, [&preperm](int const&i
swap(get(i), get(q[i])); )->int&{return preperm[i];});
swap(q[i], q[q[i]]); ret.second.swap(preperm);
} return ret;
} }
} template<typename T>
// ret.first is the sorted vector ret.second[i] is the static pair<vector<T>, vector<int> > sort(vector<T> v)
// index of the i-th smallest element in the original {
vector return sort(move(v), std::less<T>{});
// i.e. ret.second is the permutation that was applied }
to sort };
template<typename T, typename F>
static pair<vector<T>, vector<int> > sort(vector<T> v, 7.3 DP Optimizations
F comp){
const int n = v.size(); A[i][j] : The smallest k that gives optimal answer
if(n <= 1) return {move(v), {{0}}};
vector<int> preperm(n); Divide and Conquer:
iota(preperm.begin(), preperm.end(), 0); dp[i][j] = min(k < j){dp[i - 1][k] + C[k][j]}
const int M = n-n/2; O(kn^2) -> O(knlog(n))
for(int i=0;i<n/2;++i){ Conditions:
if(comp(v[M+i], v[i])){ A[i][j] <= A[i][j + 1] OR
swap(v[M+i], v[i]); C[a][d] + C[b][c] >= C[a][c] + C[b][d] where a < b <
swap(preperm[M+i], preperm[i]); c < d
}
} Short Description:
auto ret=sort(vector<T>(v.begin(),v.begin()+n/2), A[i][1] <= A[i][2] <= ... <= A[i][n]
comp); Knuth Optimization:
apply_permutation(ret.second,[&preperm,M](int const& dp[i][j] = min(i < k < j){dp[i][k] + dp[k][j]} + C[i][
i)->int&{return preperm[M+i];}); j]
apply_permutation(ret.second,[&preperm](int const&i) O(n^3) -> O(n^2)
->int&{return preperm[i];});
apply_permutation(ret.second,[&v,M](int const&i)->T Conditions:
&{return v[M+i];}); A[i, j - 1] <= A[i, j] <= A[i + 1, j] OR
iota(ret.second.begin(), ret.second.end(), 0); C[a][d] + C[b][c] >= C[a][c] + C[b][d] AND
// insert one element without comparisons C[b][c] <= C[a][d] where a <= b <= c <= d
ret.first.push_back(v.back()); Short Description:
ret.second.push_back(n-1); For dp[i][j], loop k from A[i][j - 1] to A[i + 1][j]
// now insert the rest in blocks that optimize the
binary search sizes
for(int it=1,r=n-1,s=2; r>n/2; ++it, r-=s, s=(1<<it) 7.4 Convex Hull Trick (Dynamic)
-s){
for(int i=r-s;i<r;++i){ struct Line {
if(i>=n/2){ long long m, b;
int a = find(ret.second.begin(), ret.second. mutable function<const Line*()> succ;
end(), i-M) - ret.second.begin(); bool operator<(const Line& rhs) const{
int b = ret.first.size(); if(rhs.b!=-(1ll<<62)) return m>rhs.m; // < for max
if(a==b) { const Line* s = succ();
assert(i==M-1); if (!s) return 0;
a = -1; return b-s->b > (s->m -m)*rhs.m; // < for max
} }
};
22
IIIT-Delhi - Cogito Ergo Error

struct HullDynamic : public multiset<Line> { }


bool bad(iterator y) { // Get the minimum value of mx + b among all lines in
auto z = next(y); the structure.
if(y==begin()){ // There must be at least one line.
if(z==end())return 0; LL query(LL x) {
return y->m == z->m && y->b >= z->b; // <= for max int i = upper_bound(left.begin(), left.end(), x) -
} left.begin();
auto x = prev(y); return M[i-1]*x + B[i-1];
if (z==end()) return y->m == x->m && y->b >= x->b; }
// <= for max };
return (x->b - y->b)*1.0*(z->m - y->m) >= (y->b - z
->b)*1.0*(y->m - x->m);
} 7.6 BigInt library
void insert_line(long long m, long long b) {
auto y = insert({ m, b }); struct bignum {
y->succ = [=]{return next(y)==end()? 0:&*next(y);}; typedef unsigned int uint;
if(bad(y)) { erase(y); return; } vector<uint> digits;
while(next(y)!=end() && bad(next(y)))erase(next(y)); static const uint RADIX = 1000000000;
while(y!=begin() && bad(prev(y)))erase(prev(y)); bignum(): digits(1, 0) {}
} bignum(const bignum& x): digits(x.digits) {}
long long eval(long long x) { bignum(unsigned long long x) {*this = x;}
auto l = *lower_bound((Line){x,-(1ll<<62)}); bignum(const char* x) {*this = x;}
return l.m * x + l.b; bignum(const string& s) {*this = s;}
} bignum& operator=(const bignum& y)
}; {digits = y.digits; return *this;}
bignum& operator=(unsigned long long x){
digits.assign(1, x%RADIX);
7.5 Convex Hull Trick (Static) if (x >= RADIX)
digits.push_back(x/RADIX);
struct ConvexHullTrick { return *this;
typedef long long LL; }
vector<LL> M; bignum& operator=(const char* s) {
vector<LL> B; int slen=strlen(s),i,l;
vector<double> left; digits.resize((slen+8)/9);
ConvexHullTrick() {} for (l=0; slen>0; l++,slen-=9) {
bool bad(LL m1, LL b1, LL m2, LL b2, LL m3, LL b3) { digits[l]=0;
// Careful, this may overflow for (i=slen>9?slen-9:0; i<slen; i++)
return (b3-b1)*(m1-m2) < (b2-b1)*(m1-m3); digits[l]=10*digits[l]+s[i]-’0’;
} }
// Add a new line to the structure, y = mx + b. while (digits.size() > 1 && !digits.back()) digits.
// Lines must be added in decreasing order of slope. pop_back();
void add(LL m, LL b) { return *this;
while (M.size() >= 2 && bad(M[M.size()-2], B[B.size }
()-2], M.back(), B.back(), m, b)) { bignum& operator=(const string& s)
M.pop_back(); B.pop_back(); left.pop_back(); {return *this = s.c_str();}
}
if (M.size() && M.back() == m) { void add(const bignum& x) {
if (B.back() > b) { int l = max(digits.size(), x.digits.size());
M.pop_back(); B.pop_back(); left.pop_back(); digits.resize(l+1);
} else { for (int d=0, carry=0; d<=l; d++) {
return; uint sum=carry;
} if (d<digits.size()) sum+=digits[d];
} if (d<x.digits.size()) sum+=x.digits[d];
if (M.size() == 0) { digits[d]=sum;
left.push_back(-numeric_limits<double>::infinity() if (digits[d]>=RADIX)
); digits[d]-=RADIX, carry=1;
} else { else
left.push_back((double)(b - B.back())/(M.back() - carry=0;
m)); }
} if (!digits.back()) digits.pop_back();
M.push_back(m); }
B.push_back(b); void sub(const bignum& x) {
23
IIIT-Delhi - Cogito Ergo Error

// if ((*this)<x) throw; //negative numbers not yet }


supported if (dividend >= divisor) { dividend -= divisor;
for (int d=0, borrow=0; d<digits.size(); d++) { digits[pwr]++; }
digits[d]-=borrow; pwr--; divisor.digits.erase(divisor.digits.begin()
if (d<x.digits.size()) digits[d]-=x.digits[d]; );
if (digits[d]>>31) { digits[d]+=RADIX; borrow=1; } }
else borrow=0; while (digits.size() > 1 && !digits.back()) digits.
} pop_back();
while (digits.size() > 1 && !digits.back()) digits. return dividend;
pop_back(); }
} string to_string() const {
void mult(const bignum& x) { ostringstream oss;
vector<uint> res(digits.size() + x.digits.size()); oss << digits.back();
unsigned long long y,z; for (int i = digits.size() - 2; i >= 0; i--) {
for (int i=0; i<digits.size(); i++) { oss << setfill(’0’) << setw(9) << digits[i];
for (int j=0; j<x.digits.size(); j++) { }
unsigned long long y=digits[i]; y*=x.digits[j]; return oss.str();
unsigned long long z=y/RADIX; }
res[i+j+1]+=z; res[i+j]+=y-RADIX*z; //mod is bignum operator+(const bignum& y) const
slow {bignum res(*this); res.add(y); return res;}
if (res[i+j] >= RADIX) { res[i+j] -= RADIX; res[ bignum operator-(const bignum& y) const
i+j+1]++; } {bignum res(*this); res.sub(y); return res;}
for (int k = i+j+1; res[k] >= RADIX; res[k] -= bignum operator*(const bignum& y) const
RADIX, res[++k]++); {bignum res(*this); res.mult(y); return res;}
} bignum operator/(const bignum& y) const
} {bignum res(*this); res.div(y); return res;}
digits = res; bignum operator%(const bignum& y) const
while (digits.size() > 1 && !digits.back()) digits. {bignum res(*this); return res.div(y);}
pop_back(); bignum& operator+=(const bignum& y)
} {add(y); return *this;}
// returns the remainder bignum& operator-=(const bignum& y)
bignum div(const bignum& x) { {sub(y); return *this;}
bignum dividend(*this); bignum& operator*=(const bignum& y)
bignum divisor(x); {mult(y); return *this;}
fill(digits.begin(), digits.end(), 0); bignum& operator/=(const bignum& y)
// shift divisor up {div(y); return *this;}
int pwr = dividend.digits.size() - divisor.digits. bignum& operator%=(const bignum& y)
size(); {*this = div(y);}
if (pwr > 0) { bool operator==(const bignum& y)
divisor.digits.insert(divisor.digits.begin(), pwr, {return digits == y.digits;}
0); bool operator<(const bignum& y) const {
} if (digits.size() < y.digits.size()) return true;
while (pwr >= 0) { if (digits.size() > y.digits.size()) return false;
if (dividend.digits.size() > divisor.digits.size() for (int i = digits.size()-1; i >= 0; i--)
) { if (digits[i] < y.digits[i])
unsigned long long q = dividend.digits.back(); return true;
q *= RADIX; q += dividend.digits[dividend.digits else if (digits[i] > y.digits[i])
.size()-2]; return false;
q /= 1+divisor.digits.back(); return false;
dividend -= divisor*q; digits[pwr] = q; }
if (dividend >= divisor) { digits[pwr]++; bool operator>(const bignum& y) const
dividend -= divisor; } {return y<*this;}
assert(dividend.digits.size() <= divisor.digits. bool operator<=(const bignum& y) const
size()); continue; {return !(y<*this);}
} bool operator>=(const bignum& y) const
while (dividend.digits.size() == divisor.digits. {return !(*this<y);}
size()) { };
uint q = dividend.digits.back() / (1+divisor.
digits.back());
if (q == 0) break;
digits[pwr] += q; dividend -= divisor*q; 7.7 Manachers algorithm
24
IIIT-Delhi - Cogito Ergo Error

// Ex: "opposes" -> [0,1,0,1,4,1,0,1,0,1,0,3,0,1,0] return dayOfWeek[jd % 7];


vector<int> fastLongestPalindromes(string str) { }
int i=0,j,d,s,e,lLen,palLen=0;
vector<int> res;
while (i < str.length()) { 7.9 Bitset (Text)
if (i > palLen && str[i-palLen-1] == str[i]) {
palLen += 2; i++; continue; Remember _Find_first() and _Find_next() ex- ist, and run
} in O(N/W), where W is word size of machine.
res.push_back(palLen);
s = res.size()-2;
e = s-palLen; 7.10 Template
bool b = true;
for (j=s; j>e; j--) { g++ -std=c++17 -DLOCAL -O2 -Wall -Wshadow -Wextra -
d = j-e-1; pedantic -Wfloat-equal -Wlogical-op
if (res[j] == d) { palLen = d; b = false; break; } #pragma comment(linker, "/stack:200000000")
res.push_back(min(d, res[j])); #pragma GCC optimize("Ofast")
} #pragma GCC optimize ("unroll-loops")
if (b) { palLen = 1; i++; } #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,
} mmx,avx,tune=native") // codeforces
res.push_back(palLen); //#pragma GCC target("avx,avx2,fma")
lLen = res.size(); //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,
s = lLen-2; abm,mmx,tune=native") // yandex
e = s-(2*str.length()+1-lLen);
for (i=s; i>e; i--) { d = i-e-1; res.push_back(min(d, #include <ext/pb_ds/assoc_container.hpp>
res[i])); } #include <ext/pb_ds/tree_policy.hpp>
return res; #include <bits/stdc++.h>
}
using namespace __gnu_pbds;
using namespace std;
7.8 Dates typedef long double ld;
// Months are expressed as integers from 1 to 12, Days typedef long long ll;
are expressed as integers from 1 to 31, and Years are typedef pair <int, int> pii;
expressed as 4-digit integers. typedef pair <ll, ll> pll;
string dayOfWeek[] = {"Mon", "Tue", "Wed", "Thu", "Fri",
"Sat", "Sun"}; mt19937 rng(std::chrono::duration_cast<std::chrono::
nanoseconds>(chrono::high_resolution_clock::now().
//converts Gregorian date to integer(Julian day number) time_since_epoch()).count());
int dateToInt (int m, int d, int y){
return template<typename has_less>
1461 * (y + 4800 + (m - 14) / 12) / 4 + using ordered_set =
367 * (m - 2 - (m - 14) / 12 * 12) / 12 - tree<has_less,
3 * ((y + 4900 + (m - 14) / 12) / 100) / 4 + null_type,
d - 32075; less<has_less>,
} rb_tree_tag,
// converts integer (Julian day number) to Gregorian tree_order_statistics_node_update>;
date: month/day/year //insert using pref_trie.insert
void intToDate (int jd, int &m, int &d, int &y){ //get range for prefix using pref_trie.prefix_range
int x, n, i, j; //use iterator from range.first until != range.second
x = jd + 68569; typedef
n = 4 * x / 146097; trie<string,
x -= (146097 * n + 3) / 4; null_type,
i = (4000 * (x + 1)) / 1461001; trie_string_access_traits<>,
x -= 1461 * i / 4 - 31; pat_trie_tag,
j = 80 * x / 2447; trie_prefix_search_node_update>
d = x - 2447 * j / 80; pref_trie;
x = j / 11;
m = j + 2 - 12 * x; struct chash {
y = 100 * (n - 49) + i + x; int operator()(int x) const { return x ^ RANDOM; }
} };
gp_hash_table<key, int, chash> table;
// converts integer (Julian day number) to day of week
string intToDay (int jd){ int main(){}
25
IIIT-Delhi - Cogito Ergo Error

static typename result_of<Func(S)>::type integrate(


7.11 Numerical Integration Func f, S const l, S const r, size_t const steps){
assert(steps>0);
// different schemes for numerical integration typename result_of<Func(S)>::type ret(0);
// approximatively ordered by accuracy S cur_l = l, cur_r;
// do NOT use integer types for integration range! for(size_t i=0;i<steps;++i){
struct Integration_Midpoint{ cur_r = (l*(steps-i-1) + r*(i+1))/steps;
template<typename Func, typename S> ret+=Integration_Method::integrate_step(f, cur_l,
static typename result_of<Func(S)>::type cur_r);
integrate_step(Func f, S l, S r){ cur_l = cur_r;
S m = (l+r)/2; }
return f(m) * (r-l); return ret;
} }
}; };
struct Integration_Simpson{ template<typename Integration_Method>
template<typename Func, typename S> class Integrator_Adaptive{
static typename result_of<Func(S)>::type private:
integrate_step(Func f, S l, S r){ template<size_t depth_limit, typename Func, typename S
S m = (l+r)/2; >
return (f(l) + 4*f(m) + f(r))/6 * (r-l); static typename result_of<Func(S)>::type integrate(
} Func f, S const l, S const r, typename result_of<
}; Func(S)>::type const val, typename result_of<Func(S
struct Integration_Gauss_2{ )>::type const eps, const size_t depth){
static constexpr long double A = 1.0l/sqrtl(3)/2, x1 if(depth>=depth_limit){
=0.5l-A, x2 = 0.5l+A; return val;
template<typename Func, typename S> }
static typename result_of<Func(S)>::type S const m = (l+r)/2;
integrate_step(Func f, S l, S r){ typename result_of<Func(S)>::type val_l =
return (f(l*x1 + r*x2) + f(l*x2+r*x1))/2 * (r-l); Integration_Method::integrate_step(f, l, m);
} typename result_of<Func(S)>::type val_r =
}; Integration_Method::integrate_step(f, m, r);
struct Integration_NCotes_Open_4{ typename result_of<Func(S)>::type error = abs(val -
template<typename Func, typename S> val_l - val_r);
static typename result_of<Func(S)>::type if(error < eps){
integrate_step(Func f, S l, S r){ return val_l + val_r;
S h = (r-l)/5; }
return (11*f(l+h) + f(l+2*h) + f(r-2*h) + 11*f(r-h)) return integrate<depth_limit>(f, l, m, val_l, eps/2,
/24 * (r-l); depth+1)
} + integrate<depth_limit>(f, m, r, val_r, eps/2,
}; depth+1);
struct Integration_Gauss_3{ }
static constexpr long double A = sqrtl(3.0l/5.0l)/2, public:
x1=0.5-A, x2 = 0.5+A; template<size_t depth_limit, typename Func, typename S
template<typename Func, typename S> >
static typename result_of<Func(S)>::type static typename result_of<Func(S)>::type integrate(
integrate_step(Func f, S l, S r){ Func f, S const l, S const r, typename result_of<
return (5*f(l*x1 + r*x2) + 8*f((l+r)/2) + 5*f(l*x2+r Func(S)>::type const eps){
*x1))/18 * (r-l); return integrate<depth_limit>(f, l, r,
} Integration_Method::integrate_step(f, l, r), eps,
}; 0);
}
template<typename Integration_Method> };
struct Integrator_Fixedstep{
template<typename Func, typename S>

You might also like