Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
21 views

Stanford Python Codebook

Stanford ICPC Python Codebook

Uploaded by

scl019
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views

Stanford Python Codebook

Stanford ICPC Python Codebook

Uploaded by

scl019
Copyright
© © All Rights Reserved
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