KEMBAR78
Competitive Programming C++ Cheatsheet | PDF | C++ | Theoretical Computer Science
0% found this document useful (0 votes)
353 views23 pages

Competitive Programming C++ Cheatsheet

The document is a comprehensive C++ cheatsheet for competitive programming, covering major algorithms, data structures, and templates. It includes ready-to-use code snippets for various topics such as mathematics, bit manipulation, data structures, searching algorithms, recursion, and graph algorithms. Each section provides essential techniques and implementations to facilitate quick recall and application in competitive programming scenarios.

Uploaded by

Ashutosh
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)
353 views23 pages

Competitive Programming C++ Cheatsheet

The document is a comprehensive C++ cheatsheet for competitive programming, covering major algorithms, data structures, and templates. It includes ready-to-use code snippets for various topics such as mathematics, bit manipulation, data structures, searching algorithms, recursion, and graph algorithms. Each section provides essential techniques and implementations to facilitate quick recall and application in competitive programming scenarios.

Uploaded by

Ashutosh
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/ 23

Competitive Programming C++ Cheatsheet

This comprehensive document organizes all major algorithms, data structures, and templates for
competitive programming in C++. Each section contains ready-to-use code snippets for fast
recall and implementation.

1. Basic Templates
Template 1

#include <bits/stdc++.h>
using namespace std;
#define IOS ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl '\n'
using ll=int64_t;

signed main() {
IOS int _t;cin>>_t;
while (_t--) {

}
}

Template 2

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
//using ll=int64_t;
#define int long long

void solve() {

#undef int
int main() {
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int _t;cin>>_t;while (_t--)
solve();
}
2. Mathematics
Binary Exponentiation (Recursive)

ll binexp(ll a, ll b, ll p_=1e9+7) { //log(b)


if (!b) return 1;
if (b%2) return a*binexp(a, b-1, p_)%p_;
ll _=binexp(a,b>>1LL,p_);
return _*_%p_;
}

Binary Exponentiation (Iterative)

long long binexp(long long a, long long b, long long m) {


a %= m;
long long res = 1;
while (b > 0) {
if (b & 1)
res = res * a % m;
a = a * a % m;
b >>= 1;
}
return res;
}

Prime Factorization

unordered_map<ll,ll> get_divisors(ll n) { //O(sqrt(n))


unordered_map<ll,ll> ans;
ll _=sqrt(n);
for (ll i=2;i<=_;i++)
while (!(n%i)) {
ans[i]++;
n/=i;
}
if (n>1) ans[n]++;
return ans;
}

Euclidean GCD

ll gcd(ll a, ll b) { //O(log(min(a,b)))
if (!a) return b;
if (a>b) swap(a,b);
return gcd(b%a, a);
}

Sieve of Eratosthenes
vector<bool> get_prime_sieve(ll n) {//O(nloglogn)
vector<bool> is_prime(n+1, true);
is_prime[^0]=is_prime[^1]=false;
for (ll i=2;i<=n;i++)
if (is_prime[i])
for (ll j=i*i; j<=n; j+=i)
is_prime[j]=false;
return is_prime;
}

Primes up to n

vector<ll> get_primes_upto(ll n) {//O(nloglogn)


vector<ll> vc;
vector<bool> is_prime(n+1, true);
is_prime[^0]=is_prime[^1]=false;
for (ll i=2;i<=n;i++)
if (is_prime[i]) {
vc.push_back(i);
for (ll j=i*i; j<=n; j+=i)
is_prime[j]=false;
}
return vc;
}

Segmented Sieve

vector<bool> get_segmented_sieve(ll a, ll b) {//O((b-a)loglogb)


vector<bool> is_prime(b-a+1, true);
for (ll i:get_primes_upto(sqrt(b))) {
for (ll j=max(i*i, (a+i-1)/i*i); j<=b;j+=i)
is_prime[j-a]=false;
}
return is_prime;
}

Fast Factorization (Smallest Prime Array)

vector<int> sp;
void gen_sp_array(ll n) { //O(nloglogn)
sp.resize(n);
for (int i=2;i<n;i++)
sp[i]=i;
for (int i=2;i<n;i++)
if (sp[i]==i)
for (ll j=1LL*2*i; j<=sp.size();j+=i)
sp[j]=i;
}

unordered_map<ll,ll> get_divisors_fast(ll a) { //O(loga)


unordered_map<ll,ll> factors;
while (a>1) {
factors[sp[a]]++;
a /= sp[a];
}
return factors;
}

Binomial Coefficient (Mod M)

vector<ll> fact, inv_fact;


void build_C(int N=100000, ll M=1e9+7) { //O(n)
fact.assign(N+1,0); inv_fact.assign(N+1,0);
fact[^0]=fact[^1]=1;
for (int i=2;i<=N;i++)
fact[i]=(fact[i-1]*i)%M;
inv_fact[N]=binexp(fact[N], M-2);
for (int i=N; i>=1;i--)
inv_fact[i-1]=(i*inv_fact[i])%M;
}

ll C(ll n, ll r, ll M=1e9+7) { //O(1)


if (r>n) return 0;
return fact[n]*inv_fact[n-r]%M*inv_fact[r]%M;
}

Power of Prime in n!

ll power_of_prime(ll n, ll p) { //O(logn)
ll ans=0;
while (n) ans+=(n/=p);
return ans;
}

3. Bit Manipulation
Basic Bitwise Functions

#define setbit(n,i) ((n)|(1LL<<(i))) //Add element to the set


#define unset(n,i) ((n)&(~(1LL<<(i)))) //Remove element
#define check(n,i) (((n)>>(i))&1LL) //Is present?
#define flip(n,i) ((n)^(1LL<<(i)))
#define flipall(n,i) ((n)^(~0LL))
//__builtinpopcount(x) -> Set bits
//__builtinctz(x) -> Trailing zeros
//__builtinclz(x) -> Leading zeros

#define remove_last_setbit(n) ((n)&(n-1))


#define get_last_setbit(n) ((n)&(~(n-1)))

Bit Trie
struct node {
int child[^2];
int cnt=0;
node () {
memset(child,-1,sizeof(child));
}
};

#define LN 32
struct bittrie {
vector<node> nodes;
bittrie() {
node root;
nodes.push_back(root);
}

void insert(ll x) {
int cur_node=0;
for (int i=LN-1;i>=0;--i) {
int v=(x>>i)&1;
if (nodes[cur_node].child[v]==-1) {
node new_node;
nodes.push_back(new_node);
nodes[cur_node].child[v]=nodes.size()-1;
}
nodes[cur_node].cnt++;
cur_node=nodes[cur_node].child[v];
}
nodes[cur_node].cnt++;
}

void erase(ll x) {
int cur_node=0;
for (int i=LN-1;i>=0;--i) {
int v=(x>>i)&1;
nodes[cur_node].cnt--;
cur_node=nodes[cur_node].child[v];
}
nodes[cur_node].cnt--;
}

ll query(ll x) {
ll y=0;
int cur_node=0;
for (int i=LN-1;i>=0;--i) {
int v=(x>>i)&1;
if (nodes[cur_node].child[!v]!=-1 && nodes[nodes[cur_node].child[!v]].cnt>0)
if ((!v)==1) y|=(1ll<<i);
cur_node=nodes[cur_node].child[!v];
} else {
if (v==1) y|=(1ll<<i);
cur_node=nodes[cur_node].child[v];
}
}
return x^y;
}
};

4. Data Structures
Monotone Deque

template <class T>


struct monotone_deque {
deque<T> dq;
void insert(T k) {
while (!dq.empty() && dq.back()>k)
dq.pop_back();
dq.push_back(k);
}
void erase(T k) {
if (dq.front() == k)
dq.pop_front();
}
int min() {
if (!dq.empty())
return dq.front();
else return INT_MIN;
}
};

Indexed Set (PBDS)

#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less<int>, rb_tree_tag,
tree_order_statistics_node_update>
indexed_set;
//order_of_key: Number of items strictly smaller than k
//find_by_order: Iterator to the ith largest element

Next Greatest Element (Monotone Stack)

stack<int> st_index;
int ngi[n];
for (int i = n-1; i>=0; i--) {
while (!st_index.empty() && arr[st_index.top()] <= arr[i])
st_index.pop();
if (st_index.empty())
ngi[i] = n;
else ngi[i] = st_index.top();
st_index.push(i);
}
5. Searching Algorithms
Binary Search (Basic)

ll lo=0, hi=_upper_limit_, ans=_default_value_;


while (hi>=lo) {
ll mid=(lo+hi)/2;
if (check(arr, mid)) {
ans=mid;
hi=mid-1;
} else lo=mid+1;
}

Ternary Search

ll lo = 0, hi = a/b;
while (hi-lo>3) {
ll mid1 = (lo*2+hi)/2;
ll mid2 = (lo+hi*2)/2;
if (func(mid1)>func(mid2)) //For Minima
lo= mid1;
else hi = mid2;
}
ld ans=a;
for (ll i=lo; i<=hi; i++)
ans = min(ans, func(i));

Binary Search (Real Domain)

ld lo=0.0, hi=__upper_limit__, ans=0.0;


while (abs(lo-hi)>1e-9) {
ld mid=(lo+hi)/2.0;
if (check(mid)) {
ans=mid;
lo=mid;
}else hi=mid;
}
cout << fixed<<setprecision(6)<<ans<< endl;

Two Pointer (from Start)

int head=-1, tail=0;


__ds__
int ans=0;
while (tail<n) {
while (head+1<n && __condition_for_head_to_move_forward__) {
head++;
__do_something_on_ds__
}
ans=__update_ans__;

if (head>=tail) {
__do_reset_something_on_ds__
tail++;
} else {
tail++;
head=tail-1;
}
}

Two Pointers (Both Sides)

int i=0, k=n-1;


while (i<j && j<k) {
if (arr[i]+arr[j]+arr[k]==T) {
int itemp=i;
int ktemp=k;
while (itemp<j && arr[itemp]==arr[i])
itemp++;
while (ktemp>k && arr[ktemp]==arr[k])
ktemp--;
cnt+=(itemp-i)*(k-ktemp);
i=itemp;
k=ktemp;
} else if (arr[i]+arr[j]+arr[k]<T)
i++;
else k--;
}

6. Recursion, D&C, Backtracking, and Miscellaneous


LLCM Framework (Backtracking)

/*
The LCCM framework for backtracking.
Choose the DS used to store the current configuration.
O(ch1*ch2......*chn*(Base recursion complexity + sum(all checks)))
L - Level
C - Choice
C - Check function (For checking the validity of the choice)
M - Move (Change config., Level up and recurse, Restore config.)

void rec(T lvl)


__breaking_condition__ //Base case where answer is updated
for (all choices)
check(choice)
move(lvl+1)
*/

Merge Sort (DnC)

vector<int> mergesort(vector<int> &arr) { //O(nlogn)


int n=arr.size();
if (n==1) return arr;
vector<int> ans;ans.resize(n);
vector<int> p[^2];
for (int i=0;i<n;i++) p[i&1].push_back(arr[i]);
vector<int> s1=mergesort(p[^0]), s2=mergesort(p[^1]);
int i=0,j=0,k=0;
while (i<s1.size() && j<s2.size()) {
if (s1[i]<=s2[j])
ans[k++]=s1[i++];
else ans[k++]=s2[j++];
}
while (i<s1.size()) ans[k++]=s1[i++];
while (j<s2.size()) ans[k++]=s2[j++];
return ans;
}

Meet in the Middle


(No direct code; used for subset/4sum problems. Split set, enumerate all sums of subsets,
combine using binary search or hashing.)

7. Graph Algorithms
Adjacency List Input

vector<vector<int>> g;
vector<bool> vis;
int n,m; cin>>n>>m;
g.resize(n+1);
for (int i=0;i<m;i++) {
int a, b;
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a); //If undirected
}
vis.assign(n+1,0);

DFS Outline

void dfs(node x) {
// Mark node x as visited.
// Do some operation on the node like coloring, component id...
for (node neighbour:adj_list[x])
if (Not marked visited)
dfs(neighbour);
}

BFS Template (Unweighted)

using state=pair<int,int>;
vector<vector<int>> dis;
vector<vector<bool>> vis;
vector<state> get_neighbours(state node) {
//Fill in
}

void bfs(state st_node) {


queue<state> q;
dis[st_node.F][st_node.S]=0;
q.push(st_node);
while (!q.empty()) {
auto tp=q.front();
q.pop();
if (vis[tp.F][tp.S])continue;
vis[tp.F][tp.S]=1;
for (auto &k:get_neighbours(tp)) {
if (dis[k.F][k.S]>dis[tp.F][tp.S]+1) {
dis[k.F][k.S]=dis[tp.F][tp.S]+1;
q.push(k);
}
}
}
}

Cycle Detection (DFS Coloring)

vector<int> col;
bool is_cycle=0;

void dfs(int node, int p) {


col[node]=2; //mark it visited
for (auto v:g[node]) {
//if (v==p) continue; //necessary for undirected
if (col[v]==1) {
dfs(v, node);
} else if (col[v]==2) {
is_cycle=true;
}
}
col[node]=3;
}

Topological Sort (Kahn's Algorithm)

vector<int> indeg;
vector<int> topo;
void kahn() {
queue<int> q;
for (int i=1;i<=n;i++)
if (indeg[i]==0)
q.push(i);
while (!q.empty()) {
int cur=q.front();
q.pop();
topo.push_back(cur);
for (auto v:g[cur]) {
indeg[v]--;
if (indeg[v]==0)q.push(v);
}
}
}

0/1 BFS

vector<int> dist;
vector<bool> vis;

void BFS01(int sc) {


deque<int> q;
dist[sc]=0;
q.push_back(sc);

while (!q.empty()) {
int cur=q.front();
q.pop_front();
if (vis[cur]) continue;
vis[cur]=1;

for (auto v:g[cur]) {


if (dist[v.F]>dist[cur]+v.S) {
dist[v.F]=dist[cur]+v.S;
if (v.S) q.push_back(v.F);
else q.push_front(v.F);
}
}
}
}

Dijkstra's Algorithm

class prioritize {
public: bool operator() (ii &p1, ii &p2) {
return p1.S>p2.S;
}
};

vector<lli> dist;
vector<bool> vis;

void dikstra(int sc) {


dist.assign(n+1, 1e18);
vis.assign(n+1,0);
dist[sc]=0;
priority_queue<pii, vector<pii>, prioritize> q;
q.push(MP(sc,0));
while (!q.empty()) {
pii fs=q.top(); q.pop();
if (vis[fs.F]) continue;
vis[fs.F]=1;
for (auto v:g[fs.F]) {
int neigh=v.F, wt=v.S;
if (dist[neigh]>dist[fs.F]+wt) {
dist[neigh]=dist[fs.F]+wt;
q.push({neigh, dist[neigh]});
}
}
}
}

Bellman-Ford

vector<pair<ii,int>> g;
vector<ll> dist;
vector<bool> vis;
bool neg_cyc=false;
for (int i=0;i<n;i++) {
for (auto e:g) {
if (dist[e.F.S]>dist[e.F.F]+e.S) {
dist[e.F.S]=dist[e.F.F]+e.S;
if (i==n-1) neg_cyc=true;
}
}
}

Floyd-Warshall

int n,m;
int dist[^404][^404];
int par[^404][^404];

void print_path(int i, int j) {


if (i!=j) print_path(i, par[i][j]);
cout << j << endl;
}

signed main() {
IOS cin>>n>>m;
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
if (i!=j)dist[i][j]=1e9;
for (int i=0;i<m;i++) {
int a,b,c; cin>>a>>b>>c;
dist[a][b]=min(dist[a][b],c);
}
for (int i=0;i<n;i++) {
for (int j=0;j<n;j++) {
par[i][j]=i;
}
}
for (int k=0;k<n;k++) {
for (int i=0;i<n;i++) {
for (int j=0;j<n;j++) {
if (dist[i][j]>dist[i][k]+dist[k][j]) {
dist[i][j]=dist[i][k]+dist[k][j];
par[i][j]=par[k][j];
}
}
}
}
}

Articulation Points/Bridges (Tarjan's Algorithm)

vector<bool> vis;
vector<int> tin,tlow;
unordered_set<int> art_pt;
int timer;

void dfs(int i, int p=-1) {


vis[i]=1;
tin[i]=tlow[i]=timer++;
int children=0;
for (auto v:g[i]) {
if (v==p) continue;
if (vis[v])
tlow[i]=min(tlow[i], tin[v]);
else {
dfs(v, i);
tlow[i]=min(tlow[i], tlow[v]);
if (tlow[v]>=tin[i] && p!=-1)
art_pt.insert(v);
children++;
}
}
if (p==-1 && children>1)
art_pt.insert(i);
}

Union Find (Disjoint Set)

class UnionFind {
private:
int n,set_size, *parent, *rank;
public:
UnionFind(){}
UnionFind(int a) {
n=set_size=a;
parent=new int[n+1];
rank=new int[n+1];
for (int i=1;i<=n;i++) parent[i]=i, rank[i]=1;
}
int find(int x) {
if (x!=parent[x]) return parent[x]=find(parent[x]);
return x;
}
bool merge(int x, int y) {
int xroot=find(x), yroot=find(y);
if (xroot!=yroot) {
if (rank[xroot]>=rank[yroot]) {
parent[yroot]=xroot;
rank[xroot]+=rank[yroot];
} else {
parent[xroot]=yroot;
rank[yroot]+=rank[xroot];
}
set_size--;
return 1;
}
return 0;
}
void reset() {
set_size=n;
for (int i=1;i<=n;i++) parent[i]=i, rank[i]=1;
}
};

Kruskal's Algorithm

UnionFind uf(n);
vector<pair<int,ii>> edge_list;
int a,b,c;
for (int i=0;i<m;i++) {
cin>>a>>b>>c;
edge_list.push_back({c,{a,b}});
}
sort(edge_list.begin(), edge_list.end());

int mst_cost=0;
for (auto v:edge_list) {
int x=v.S.F, y=v.S.S;
if (uf.find(x)!=uf.find(y)) {
mst_cost+=v.first;
uf.merge(x,y);
}
}
cout << mst_cost << endl;

Kosaraju’s Algorithm (SCC)

vector<vector<int>> g, grev;
vector<int> vis(100100,0);
vector<int> tout_order;
void dfs1(int x) {
vis[x]=1;
for (auto v:g[x]) {
if(!vis[v])
dfs1(v);
}
tout_order.push_back(x);
}
int cur_scc=0;
int scc_num[^100100];
void dfs2(int x) {
scc_num[x]=cur_scc;
vis[x]=1;
for (auto v:grev[x])
if (!vis[v])
dfs2(v);
}
vector<vector<int>> condensed_graph;

void condense() {
for (int i=1;i<=n;i++)
if (!vis[i])
dfs1(i);
reverse(tout_order.begin(), tout_order.end());
vis.assign(n+1,0);
for (auto x:tout_order)
if (!vis[x]) {
cur_scc++;
dfs2(x);
}
condensed_graph.resize(cur_scc+1);
for (int i=1;i<=n;i++) {
for (auto v:g[i]) {
if (scc_num[i]!=scc_num[v])
condensed_graph[scc_num[i]].push_back(scc_num[v]);
}
}
}

8. Trees
Tree Implementation

vector<vector<int>> g;
vector<int> dep, par, subtree_sz, numChild;
vector<bool> is_leaf;

void dfs(int node, int parent, int depth) {


dep[node]=depth;
par[node]=parent;
subtree_sz[node]=1;
numChild[node]=0;
for (auto v:g[node]) {
if (v!=parent) {
numChild[node]++;
dfs(v, node, depth+1);
subtree_sz[node]+=subtree_sz[v];
}
}
if (!numChild[node])
is_leaf[node]=1;
}
Tree Diameter

void dotree(int node, int parent, int depth, vector<vector<int>>&g,vector<int>&dep,vector


dep[node]=depth;
par[node]=parent;
for (auto v:g[node]) if (v!=parent)
dotree(v, node, depth+1,g,dep,par);
}

//Diameter
vector<int> dep, par; dep.resize(n); par.resize(n);
dotree(0,-1,0,g,dep,par);
int max_dep_node=0;
for (int i=0;i<n;i++) if (dep[i]>dep[max_dep_node])max_dep_node=i;
dotree(max_dep_node,-1,0,g,dep,par);
max_dep_node=0;
for (int i=0;i<n;i++) if (dep[i]>dep[max_dep_node])max_dep_node=i;
int dia=dep[max_dep_node];

//Centres
vector<int> ans;
int node_=max_dep_node;
for (int i=0;i<dia/2;i++)node_=par[node_];
ans.push_back(node_);
if (dia&1) ans.push_back(par[node_]);

Tree Centroid

int get_centroid(int node, int parent) {


for (auto v:g[node])
if (v!=parent)
if (subtree_sz[v]>n/2)
return get_centroid(v, node);
return node;
}

Lowest Common Ancestor (LCA)

int n;
vector<int> g[^100100];
int depth[^100100], parent[^100100][^20];

void dfs(int node, int par, int dep) {


parent[node][^0]=par;
depth[node]=dep;
for (int i=1;i<20;i++) {
parent[node][i]=parent[parent[node][i-1]][i-1];
}
for (auto v:g[node]) {
if (v!=par)
dfs(v,node,dep+1);
}
}
int lca(int u, int v) {
if (depth[u]<depth[v]) swap(u,v);
for (int i=19;i>=0;i--)
if ((depth[u]-depth[v])&(1<<i))
u=parent[u][i];
if (u==v) return u;
for (int i=19;i>=0;i--) {
if (parent[v][i]!=parent[u][i]) {
v=parent[v][i];
u=parent[u][i];
}
}
return parent[u][^0];
}

9. Strings & Hashing


Trie (Basic)

struct node {
int child[^26];
node(){
memset(child,-1,sizeof(child));
}
};

struct trie {
vector<node> nodes;
trie() {
node rootnode;
nodes.push_back(rootnode);
}
void insert(string s) {
int cur_node_idx=0;
for (int i=0;i<s.size();i++) {
if (nodes[cur_node_idx].child[s[i]-'a']==-1) {
node new_node;
nodes.push_back(new_node);
nodes[cur_node_idx].child[s[i]-'a']=nodes.size()-1;
}
cur_node_idx=nodes[cur_node_idx].child[s[i]-'a'];
}
}
int get_node_count() {
return nodes.size();
}
};

KMP Algorithm
string s;cin>>s;
int n=s.length();
int kmp[n+1];
int i=0,j=-1; kmp[^0]=-1;
while (i<n) {
while (j!=-1 && s[i]!=s[j]) j=kmp[j];
j++;i++;
kmp[i]=j;
}

Z Algorithm

vector<int> z_function(string s) {
int n = s.size();
vector<int> z(n);
int l = 0, r = 0;
for(int i = 1; i < n; i++) {
if(i < r) {
z[i] = min(r - i, z[i - l]);
}
while(i + z[i] < n && s[z[i]] == s[i + z[i]]) {
z[i]++;
}
if(i + z[i] > r) {
l = i;
r = i + z[i];
}
}
return z;
}

Manacher Algorithm

struct manacher {
vector<int> p;
void run_manacher(string s) {
int n=s.length();
p.assign(n,1);
int l=1,r=1;
for (int i=1;i<n;i++) {
p[i]=max(0,min(r-i,p[l+r-i]));
while (i+p[i]<n && i-p[i]>=0 && s[i+p[i]]==s[i-p[i]]) {
p[i]++;
}
if (i+p[i]>r) {
l=i-p[i];
r=i+p[i];
}
}
}
void build(string s) {
string t;
for (auto v:s) t+=string("#")+v;
run_manacher(t+"#");
}
int getLongest(int cen, bool odd) {
int pos=2*cen+1+(!odd);
return p[pos]-1;
}
bool isPalindrome(int l, int r) {
if ((r-l+1)<=getLongest((l+r)/2,l%2==r%2))
return 1;
return 0;
}
};

Rolling Hash

ll quickHash(string s, ll p=31, ll mod=999999929) {


ll ans=s[^0]-'a'+1;
for (int i=1;i<s.length();i++)
ans=(ans*p+(s[i]-'a'+1))%mod;
return ans;
}
struct hasher {
int sz; ll mod,p;
vector<ll> fHash, rHash;
vector<ll> pk;
void init(string &s, ll _p=31, ll _mod=999999929) {
mod=_mod; p=_p;
sz=s.length();
fHash.resize(sz); pk.resize(sz);
fHash[^0]=s[^0];
pk[^0]=1;
for (int i=1;i<s.length();i++) {
fHash[i]=(fHash[i-1]*p+(s[i]-'a'+1))%mod;
pk[i]=pk[i-1]*p%mod;
}
rHash.resize(sz);
rHash[sz-1]=s.back()+1;
for (int i = sz-2; i >= 0; i--)
rHash[i] = (rHash[i + 1]*p + (s[i]-'a'+1))%mod;
}
ll getfHash(int l, int r) {
if (l==0) return fHash[r];
return ((fHash[r]-fHash[l-1]*pk[r-l+1]%mod)%mod+mod)%mod;
}
ll getrHash(int l, int r) {
if (r==sz-1) return rHash[l];
return ((rHash[l]-rHash[r+1]*pk[r-l+1]%mod)%mod+mod)%mod;
}
};
struct dhasher {
hasher h1,h2;
void init(string &s, ll p1=31, ll p2=37, ll mod1=999999929, ll mod2=999999937) {
h1.init(s,p1,mod1);
h2.init(s,p2,mod2);
}
pair<int,int> getfHash(int l, int r) {
return {h1.getfHash(l,r),h2.getfHash(l,r)};
}
};

10. Dynamic Programming


DP Basic Structure

int dp[...][...][...];
__DS__ rec(__form_state__, __aggregates__) {
//pruning

//base_case

//cache check

//transition

//save and return


}

Knapsack Merge Format

int n,k;
vector<int> g[^101];
int arr[^101];
int sz[^101];
int dp[^101][^2][^101];
void dfs(int nn, int pp) {
for (int i=0;i<=k;i++) {
dp[nn][^1][i]=(i==1?arr[nn]:-1e9);
dp[nn][^0][i]=(i==0?0:-1e9);
}
sz[nn]=1;
for (auto v:g[nn]) if (v!=pp) {
dfs(v,nn);
for (int a=sz[nn];a>=0;a--) for (int b=sz[v];b>=0;b--) {
dp[nn][^0][a+b]=max(dp[nn][^0][a+b],dp[nn][^0][a]+max(dp[v][^0][b],dp[v][^1][
dp[nn][^1][a+b]=max(dp[nn][^1][a+b],dp[nn][^1][a]+dp[v][^0][b]);
}
sz[nn]+=sz[v];
}
}

SOS DP

const int N=20;


void forward1(int *dp) {
for (int i=0;i<N;i++) for (int m=0;m<(1<<N);m++) if ((m>>i)&1)
dp[m]+=dp[m^(1<<i)];
}
void backward1(int *dp) {
for (int i=0;i<N;i++) for (int m=(1<<N)-1;m>=0;m--) if ((m>>i)&1)
dp[m]-=dp[m^(1<<i)];
}
void forward2(int *dp) {
for (int i=0;i<N;i++) for (int m=(1<<N)-1;m>=0;m--) if ((m>>i)&1)
dp[m^(1<<i)]+=dp[m];
}
void backward2(int *dp) {
for (int i=0;i<N;i++) for (int m=0;m<(1<<N);m++) if ((m>>i)&1)
dp[m^(1<<i)]-=dp[m];
}

11. Segment Trees


Segment Tree (Basic)

int n,q;
int arr[^200100];
int t[^800400]; //4*n

void build(int idx, int l, int r) {


if (l==r) { t[idx]=arr[l]; return; }
int mid=(l+r)/2;
build(idx*2,l,mid);
build(idx*2+1,mid+1,r);
t[idx]=t[2*idx]+t[2*idx+1];
}

void update(int idx, int l, int r, int pos, int val) {


if (pos<l||pos>r) return;
if (l==r) {
t[idx]=val;
return;
}
int mid=(l+r)/2;
update(idx*2,l,mid,pos,val);
update(idx*2+1,mid+1,r,pos,val);
t[idx]=t[2*idx]+t[2*idx+1];
}

int query(int idx, int l, int r, int lq, int rq) {


if (l>rq||lq>r) return 0;
if (lq<=l&&r<=rq) return t[idx];
int mid=(l+r)/2;
return query(idx*2,l,mid,lq,rq)+query(idx*2+1,mid+1,r,lq,rq);
}

Segment Tree with Lazy Propagation


struct node {
int sum,maxr,lazy;
node(){
sum=maxr=lazy=0;
}
};

node merge(node a, node b) {


node temp;
temp.sum=a.sum+b.sum;
temp.maxr=max(a.maxr,b.maxr);
return temp;
}

int n,q;
int arr[^200100];
node t[^800400];

void push(int idx, int l, int r) {


if (t[idx].lazy) {
t[idx].sum=t[idx].lazy*(r-l+1);
t[idx].maxr=t[idx].lazy;
if (l!=r) {
t[idx<<1].lazy=t[idx].lazy;
t[idx<<1|1].lazy=t[idx].lazy;
}
t[idx].lazy=0;
}
}

void update(int idx, int l, int r, int lq, int rq, int v) {
push(idx,l,r);
if (lq>r||l>rq) return;
if (lq<=l&&r<=rq) {
t[idx].lazy=v;
push(idx,l,r);
return;
}
int mid=(l+r)>>1;
update(idx<<1,l,mid,lq,rq,v);
update(idx<<1|1,mid+1,r,lq,rq,v);
t[idx]=merge(t[idx<<1],t[idx<<1|1]);
}

node query(int idx, int l, int r, int lq, int rq) {


push(idx,l,r);
if (l>rq||lq>r) return node();
if (lq<=l&&r<=rq) return t[idx];
int mid=(l+r)>>1;
return merge(query(idx<<1,l,mid,lq,rq),query(idx<<1|1,mid+1,r,lq,rq));
}

This document is ready for memorization and quick reference. Practice writing and using
these templates regularly to master competitive programming.

You might also like