Algorithm Cheat Sheet
Algorithm Cheat Sheet
10
6.3.5 Sparse SegTree (4) . . . . . . . . . . . 11
6.3.6 SegTree Beats (6) . . . . . . . . . . . 12
6.4 2D Range Queries (4) . . . . . . . . . . . . . 13
USACO Notebook: Complete 6.4.1 2D BIT . . . . . . . . . . . . . . . . . 13
6.4.2 2D SegBIT . . . . . . . . . . . . . . . 13
Benq 6.4.3 2D SegTree . . . . . . . . . . . . . . . 13
6.4.4 Merge-Sort Tree . . . . . . . . . . . . 14
February 27, 2018 6.5 BBST (4) . . . . . . . . . . . . . . . . . . . . 14
6.5.1 Treap . . . . . . . . . . . . . . . . . . 14
6.5.2 Link-Cut Tree (5) . . . . . . . . . . . 15
6.5.3 Splay Tree (5) . . . . . . . . . . . . . 16
Contents 6.6 Persistent Queries (5) . . . . . . . . . . . . . 17
6.6.1 Basic Persistent SegTree . . . . . . . . 17
1 Contest 2 6.6.2 Lazy Persistent SegTree . . . . . . . . 18
1.1 C++ Template . . . . . . . . . . . . . . . . . 2 6.6.3 Low-Memory Persistent Segment Tree 19
1.2 FastScanner . . . . . . . . . . . . . . . . . . . 2
1.3 Troubleshooting . . . . . . . . . . . . . . . . . 3 7 DP (3) 19
7.1 Examples . . . . . . . . . . . . . . . . . . . . 19
2 Sorting And Searching (2) 4 7.1.1 Knapsack . . . . . . . . . . . . . . . . 19
2.1 Interval Cover . . . . . . . . . . . . . . . . . 4 7.1.2 Longest Common Subsequence . . . . 19
2.2 Binary Search . . . . . . . . . . . . . . . . . 4 7.1.3 Longest Increasing Subsequence . . . . 19
7.1.4 String Removals . . . . . . . . . . . . 20
3 Data Structures (2) 4 7.1.5 Traveling Salesman (4) . . . . . . . . . 20
3.1 Set . . . . . . . . . . . . . . . . . . . . . . . 4 7.2 Divide And Conquer (4) . . . . . . . . . . . 20
3.1.1 Coordinate Compression . . . . . . . . 4
3.1.2 Map Customization . . . . . . . . . . 5 8 Strings (3) 20
8.1 Hashing . . . . . . . . . . . . . . . . . . . . . 20
4 Graphs Easy (2) 5 8.2 Bitset Trie (4) . . . . . . . . . . . . . . . . . 21
4.1 Traversal . . . . . . . . . . . . . . . . . . . . 5 8.3 Suffix Array (4) . . . . . . . . . . . . . . . . 21
4.1.1 BFS on Grid . . . . . . . . . . . . . . 5 8.3.1 Suffix Array . . . . . . . . . . . . . . 21
4.1.2 DFS on Graph . . . . . . . . . . . . . 5 8.3.2 Reverse Burrows-Wheeler (6) . . . . . 22
4.2 Shortest Path (3) . . . . . . . . . . . . . . . 5 8.4 Z (5) . . . . . . . . . . . . . . . . . . . . . . 22
4.2.1 Bellman-Ford . . . . . . . . . . . . . . 5 8.4.1 Aho-Corasick . . . . . . . . . . . . . . 22
4.2.2 Dijkstra . . . . . . . . . . . . . . . . . 6 8.4.2 Manacher . . . . . . . . . . . . . . . . 23
4.2.3 Floyd-Warshall . . . . . . . . . . . . . 6 8.4.3 Minimum Rotation . . . . . . . . . . . 23
4.3 Topological Sort (3) . . . . . . . . . . . . . . 6 8.4.4 Z . . . . . . . . . . . . . . . . . . . . . 24
4.4 Kruskal (3) . . . . . . . . . . . . . . . . . . . 7
9 Trees (4) 24
5 Algorithm Design (2) 7 9.1 Tree Diameter . . . . . . . . . . . . . . . . . 24
5.1 Minimum Deque (3) . . . . . . . . . . . . . . 7 9.2 Queries . . . . . . . . . . . . . . . . . . . . . 24
5.2 Ternary Search (4) . . . . . . . . . . . . . . . 7 9.2.1 Heavy-Light Set . . . . . . . . . . . . 24
9.2.2 LCA Demo . . . . . . . . . . . . . . . 25
6 Range Queries (2) 7 9.2.3 LCA with Binary Jumps . . . . . . . . 25
6.1 Static Array Queries . . . . . . . . . . . . . . 7 9.2.4 LCA with RMQ . . . . . . . . . . . . 25
6.1.1 Prefix Sums . . . . . . . . . . . . . . . 7 9.3 Advanced . . . . . . . . . . . . . . . . . . . . 26
6.1.2 Range Minimum Query (3) . . . . . . 8 9.3.1 Centroid Decomposition . . . . . . . . 26
6.1.3 Wavelet Tree (6) . . . . . . . . . . . . 8 9.3.2 Heavy-Light Decomposition . . . . . . 26
6.2 Demos (3) . . . . . . . . . . . . . . . . . . . 9
6.2.1 Point Update Demo . . . . . . . . . . 9 10 Math (4) 27
6.2.2 2D Demo (4) . . . . . . . . . . . . . . 9 10.1 Number Theory . . . . . . . . . . . . . . . . 27
6.2.3 BBST Demo (4) . . . . . . . . . . . . 9 10.1.1 Eratosthenes’ Sieve . . . . . . . . . . . 27
6.2.4 Range Update Demo (4) . . . . . . . . 9 10.1.2 Phi . . . . . . . . . . . . . . . . . . . . 27
6.3 1D Range Queries (3) . . . . . . . . . . . . . 10 10.1.3 CRT (5) . . . . . . . . . . . . . . . . . 27
6.3.1 Binary Indexed Tree . . . . . . . . . . 10 10.2 Matrices . . . . . . . . . . . . . . . . . . . . 28
6.3.2 SegTree . . . . . . . . . . . . . . . . . 10 10.2.1 Matrix Exponentiation . . . . . . . . . 28
6.3.3 BIT with Range Update (4) . . . . . . 10 10.2.2 Gaussian Elimination (6) . . . . . . . 28
1
1. CONTEST 2
11 Graphs Hard (4) 33 #define FOR(i, a, b) for (int i=a; i<(b); i++)
11.1 Kosaraju . . . . . . . . . . . . . . . . . . . . 33 #define F0R(i, a) for (int i=0; i<(a); i++)
11.2 Flows . . . . . . . . . . . . . . . . . . . . . . 33 #define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
11.2.1 Edmonds-Karp . . . . . . . . . . . . . 33 #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)
11.2.2 Flows Demo . . . . . . . . . . . . . . . 34
11.2.3 Dinic (5) . . . . . . . . . . . . . . . . 34 #define sz(x) (int)(x).size()
11.2.4 Push-Relabel (5) . . . . . . . . . . . . 35 #define mp make_pair
11.2.5 MinCostFlow (6) . . . . . . . . . . . . 35 #define pb push_back
#define f first
11.3 Tarjan BCC . . . . . . . . . . . . . . . . . . 36
#define s second
11.4 Euler Tour (6) . . . . . . . . . . . . . . . . . 37
#define lb lower_bound
#define ub upper_bound
12 Geometry (4) 37 #define all(x) x.begin(), x.end()
12.1 Techniques . . . . . . . . . . . . . . . . . . . 37
12.1.1 Pair Operators . . . . . . . . . . . . . 37 const int MOD = 1000000007;
12.1.2 Polygon Area . . . . . . . . . . . . . . 38 const double PI = 4*atan(1);
12.1.3 Line Segment Intersection (5) . . . . . 38 const ll INF = 1e18;
12.1.4 Point in Polygon (5) . . . . . . . . . . 38
12.1.5 3D Geometry (6) . . . . . . . . . . . . 39 int main() {
12.1.6 Circles (6) . . . . . . . . . . . . . . . . 39 ios_base::sync_with_stdio(0); cin.tie(0);
12.2 Sweep Line . . . . . . . . . . . . . . . . . . . 39
12.2.1 Convex Hull . . . . . . . . . . . . . . . 39 }
12.2.2 Closest Pair (6) . . . . . . . . . . . . . 40
// read the question correctly (is y a vowel?)
12.2.3 LineContainer (6) . . . . . . . . . . . 40 // look out for special cases (n=1?) and overflow (ll
12.3 Max Collinear . . . . . . . . . . . . . . . . . . 41 vs int?)
13 Additional (4) 41
13.1 Mo . . . . . . . . . . . . . . . . . . . . . . . 41
13.2 Misc . . . . . . . . . . . . . . . . . . . . . . . 41 1.2 FastScanner
13.2.1 Discrete Logarithm . . . . . . . . . . . 41
13.3 Pragma Optimization (6) . . . . . . . . . . . 42 /**
* Source: Matt Fontaine
*/
1 Contest
class FastScanner {
1.1 C++ Template private InputStream stream;
private byte[] buf = new byte[1024];
private int curChar;
/** private int numChars;
* Sources: various
*/ public FastScanner(InputStream stream) {
this.stream = stream;
#include <bits/stdc++.h> }
#include <ext/pb_ds/tree_policy.hpp> int read() {
#include <ext/pb_ds/assoc_container.hpp> if (numChars == -1)
throw new InputMismatchException();
using namespace std; if (curChar >= numChars) {
using namespace __gnu_pbds; curChar = 0;
try {
typedef long long ll; numChars = stream.read(buf);
1. CONTEST 3
} catch (IOException e) { • Are time limits close? If so, generate max cases.
throw new InputMismatchException();
} • Is the memory usage fine?
if (numChars <= 0) return -1;
} • Could anything overflow?
return buf[curChar++]; • Make sure to submit the right file.
}
Wrong answer:
boolean isSpaceChar(int c) {
return c == ’ ’ || c == ’\n’ || c == ’\r’ || c • Print your solution! Print debug output, as well.
== ’\t’ || c == -1;
} • Are you clearing all datastructures between test cases?
boolean isEndline(int c) { • Can your algorithm handle the whole range of input?
return c == ’\n’ || c == ’\r’ || c == -1;
}
• Read the full problem statement again.
• Do you handle all corner cases correctly?
public int nextInt() {
return Integer.parseInt(next()); • Have you understood the problem correctly?
}
• Any uninitialized variables?
public long nextLong() {
return Long.parseLong(next()); • Any overflows?
}
• Confusing N and M, i and j, etc.?
public double nextDouble() { • Are you sure your algorithm works?
return Double.parseDouble(next());
} • What special cases have you not thought of?
public String next() { • Are you sure the STL functions you use work as you
int c = read(); think?
while (isSpaceChar(c)) c = read();
StringBuilder res = new StringBuilder(); • Add some assertions, maybe resubmit.
do {
res.appendCodePoint(c); • Create some testcases to run your algorithm on.
c = read();
• Go through the algorithm for a simple case.
} while (!isSpaceChar(c));
return res.toString(); • Go through this list again.
}
• Explain your algorithm to a team mate.
public String nextLine() {
int c = read(); • Ask the team mate to look at your code.
while (isEndline(c))
c = read(); • Go for a small walk, e.g. to the toilet.
StringBuilder res = new StringBuilder();
• Is your output format correct? (including whitespace)
do {
res.appendCodePoint(c); • Rewrite your solution from the start or let a team mate
c = read(); do it.
} while (!isEndline(c));
return res.toString(); Runtime error:
}
} • Have you tested all corner cases locally?
• Any uninitialized variables?
1.3 Troubleshooting • Are you reading or writing outside the range of any
vector?
Source: KACTL
• Any assertions that might fail?
Pre-submit:
• Any possible division by 0? (mod 0 for example)
• Write a few simple test cases, if sample is not enough.
• Any possible infinite recursion?
2. SORTING AND SEARCHING (2) 4
int main() {
4 Graphs Easy (2) cin >> n;
F0R(i,n-1) {
4.1 Traversal int a,b; cin >> a >> b;
adj[a].pb(b);
4.1.1 BFS on Grid adj[b].pb(a);
}
/** dfs(1);
* Note: Use xdir and ydir }
*/
void process(pii x) {
F0R(i,4) { /**
pii y = {x.f+xdir[i],x.s+ydir[i]}; * Usage: https://open.kattis.com/problems/shortestpath3
if (y.f < 0 || y.f > 20 || y.s < 0 || * Description: can be useful with linear programming
y.s > 20) continue; // ignore this * Constraints of the form x_i-x_j<k
point if it’s outside of grid */
if (dist[y.f][y.s] == MOD) { // test
whether point has been visited or const ll INF = 1e18;
not
dist[y.f][y.s] = dist[x.f][x.s]+1; int n,m,q,s,bad[1000];
todo.push(y); // push point to queue vector<pair<pii,int>> edge;
} ll dist[1000];
}
} void solve() {
edge.clear();
int main() { F0R(i,n) dist[i] = INF, bad[i] = 0;
F0R(i,21) F0R(j,21) dist[i][j] = MOD; dist[s] = 0;
dist[10][10] = 0; todo.push({10,10}); // F0R(i,m) {
initialize queue, distances int u,v,w; cin >> u >> v >> w;
while (todo.size()) { edge.pb({{u,v},w});
}
4. GRAPHS EASY (2) 6
void kruskal() {
sort(all(edge)); 6 Range Queries (2)
for (auto a: edge) if (D.unite(a.s.f,a.s.s))
ans += a.f; // edge is in MST
}
6.1 Static Array Queries
6.1.1 Prefix Sums
/**
* Description: Calculates rectangle sums in constant
time
6. RANGE QUERIES (2) 8
/**
* Link: http://www.spoj.com/problems/HORRIBLE/
6.2.2 2D Demo (4)
* Description: Use with range BIT, lazy segtree
*/
/**
* Link: http://www.spoj.com/problems/MATSUM/ (modified) int main() {
* Description: Use with 2D BIT, 2D SegBIT, 2D SegTree int T; cin >> T;
*/ F0R(i,T) {
LazySegTree<ll,1<<17> B =
int main() { LazySegTree<ll,1<<17>();
BIT2D<int,1024> B = BIT2D<int,1024>(); int N, C; cin >> N >> C;
Node<int> S = Node<int>(); F0R(j,C) {
int t; cin >> t;
F0R(i,100000) { if (t == 0) {
int c = rand()&1; int p,q,v; cin >> p >> q >> v;
if (c == 0) { B.upd(p,q,v);
int x = rand() % SZ, y = rand() % SZ, num = } else {
rand() % 100; int p,q; cin >> p >> q;
S.upd(x,y,num); cout << B.qsum(p,q) << "\n";
x++, y++; }
B.upd(x,y,num); }
} else if (c == 1) { }
int x1 = rand() % SZ, y1 = rand() % SZ, x2 }
= rand() % SZ, y2 = rand() % SZ;
if (x1 > x2) swap(x1,x2);
if (y1 > y2) swap(y1,y2);
int a = S.query(x1,x2,y1,y2);
6. RANGE QUERIES (2) 10
6.3 1D Range Queries (3) for (l += SZ, r += SZ; l < r; l >>= 1, r >>=
1) {
6.3.1 Binary Indexed Tree if (l&1) res1 = comb(res1,seg[l++]);
if (r&1) res2 = comb(seg[--r],res2);
/** }
* Description: 1D range sum query with point update return comb(res1,res2);
* Verification: SPOJ Fenwick }
*/ };
void upd(int p, T value) { // set value at const ll INF = 1e18; // setting this to MOD can be
position p disastrous :(
for (seg[p += SZ] = value; p > 1; p >>= 1)
seg[p>>1] = comb(seg[(p|1)^1],seg[p|1]); // template<class T, int SZ> struct LazySegTree {
non-commutative operations T sum[2*SZ], mn[2*SZ], lazy[2*SZ]; // set SZ to a
} power of 2
T qsum(int lo, int hi, int ind = 1, int L = 0, int int M = (L+R)/2;
R = SZ-1) { if (ind <= M) {
push(ind,L,R); if (!c[0]) c[0] = new node();
if (lo > R || L > hi) return 0; c[0]->upd(ind,v,L,M);
if (lo <= L && R <= hi) return sum[ind]; } else {
if (!c[1]) c[1] = new node();
int M = (L+R)/2; c[1]->upd(ind,v,M+1,R);
return qsum(lo,hi,2*ind,L,M) + }
qsum(lo,hi,2*ind+1,M+1,R);
} val = 0;
if (c[0]) val += c[0]->val;
T qmin(int lo, int hi, int ind = 1, int L = 0, int if (c[1]) val += c[1]->val;
R = SZ-1) { }
push(ind,L,R);
if (lo > R || L > hi) return INF; T query(int low, int high, int L = 0, int R =
if (lo <= L && R <= hi) return mn[ind]; SZ-1) { // query sum of segment
if (low <= L && R <= high) return val;
int M = (L+R)/2; if (high < L || R < low) return 0;
return min(qmin(lo,hi,2*ind,L,M),
qmin(lo,hi,2*ind+1,M+1,R)); int M = (L+R)/2;
} T t = 0;
if (c[0]) t += c[0]->query(low,high,L,M);
void upd(int lo, int hi, ll inc, int ind = 1, int if (c[1]) t += c[1]->query(low,high,M+1,R);
L = 0, int R = SZ-1) { return t;
push(ind,L,R); }
if (hi < L || R < lo) return;
if (lo <= L && R <= hi) { void UPD(int ind, node* c0, node* c1, int L = 0,
lazy[ind] = inc; int R = SZ-1) { // for 2D segtree
push(ind,L,R); if (L != R) {
return; int M = (L+R)/2;
} if (ind <= M) {
if (!c[0]) c[0] = new node();
int M = (L+R)/2; c[0]->UPD(ind,c0 ? c0->c[0] : NULL,c1 ?
upd(lo,hi,inc,2*ind,L,M); c1->c[0] : NULL,L,M);
upd(lo,hi,inc,2*ind+1,M+1,R); } else {
pull(ind); if (!c[1]) c[1] = new node();
} c[1]->UPD(ind,c0 ? c0->c[1] : NULL,c1 ?
}; c1->c[1] : NULL,M+1,R);
}
}
val = 0;
6.3.5 Sparse SegTree (4)
if (c0) val += c0->val;
if (c1) val += c1->val;
/** }
* Source: Own };
*/
6. RANGE QUERIES (2) 12
const int SZ = 1<<17; T query(int x1, int x2, int y1, int y2, int L = 0,
int R = SZ-1) { // query sum of rectangle
template<class T> struct SegBit { if (x1 <= L && R <= x2) return
seg.query(y1,y2);
6. RANGE QUERIES (2) 14
snode* ins(snode* x, int v) { // insert value v Node* upd(int ind, int v, int L, int R) {
auto a = split(x,v); if (R < ind || ind < L) return this;
auto b = split(a.s,v+1); Node* x = copy();
return merge(a.f,merge(new snode(v),b.s));
} if (ind <= L && R <= ind) {
x->val += v;
snode* del(snode* x, int v) { // delete all values return x;
equal to v }
auto a = split(x,v), b = split(a.s,v+1);
return merge(a.f,b.s); int M = (L+R)/2;
} x->c[0] = x->c[0]->upd(ind,v,L,M);
x->c[1] = x->c[1]->upd(ind,v,M+1,R);
snode* root; x->val = min(x->c[0]->val,x->c[1]->val);
// https://open.kattis.com/problems/knapsack
6.6.3 Low-Memory Persistent Segment Tree
double C;
//uses about 34 MB int n,v[2000],w[2000],dp[2001][2001];
const int MAXN = 100100;
int N = 100000; void solve() {
struct Node { F0R(i,n) cin >> v[i] >> w[i];
ll val; F0R(i,n) {
} SEG[20*MAXN]; F0R(j,C+1) dp[i+1][j] = dp[i][j];
int e = 0; F0R(j,C+1) if (w[i]+j <= C) dp[i+1][w[i]+j] =
int LFT[20*MAXN], RGT[20*MAXN]; max(dp[i+1][w[i]+j],dp[i][j]+v[i]);
}
int roots[MAXN];
vi ans;
int build(int l = 0, int r = N - 1) { int x = C;
//build from L to R inclusive. F0Rd(i,n) if (dp[i][x] != dp[i+1][x]) x -= w[i],
int x = ++e; ans.pb(i);
if (l == r){
SEG[x].val = 0; cout << ans.size() << "\n";
LFT[x] = -1; for (int i: ans) cout << i << " ";
RGT[x] = -1; cout << "\n";
return x; }
}
int mid = (l + r)/2;
LFT[x] = build(l, mid);
7.1.2 Longest Common Subsequence
RGT[x] = build(mid + 1, r);
return x;
} /**
* Description: Classic DP example
int upd(int cur, int pos, int set, int l = 0, int r = */
N - 1) {
//set a[pos] = set in the root cur int dp[1001][1001];
if (r < pos || pos < l) return cur; string a,b;
int x = ++e;
//we’re creating a new node int main() {
if (l == r){ cin >> a >> b;
SEG[x].val = set; F0R(i,sz(a)) F0R(j,b.sz(b)) {
return x; dp[i+1][j+1] = max(dp[i+1][j],dp[i][j+1]);
} if (a[i] == b[j]) dp[i+1][j+1] =
int m = (l+r)/2; max(dp[i+1][j+1],dp[i][j]+1);
LFT[x] = upd(LFT[cur], pos, set, l, m); }
RGT[x] = upd(RGT[cur], pos, set, m + 1, r); cout << dp[sz(a)][sz(b)];
SEG[x].val = SEG[LFT[x]].val + SEG[RGT[x]].val; }
return x;
}
7.1.3 Longest Increasing Subsequence
ll query(int cur, int L, int R, int l = 0, int r = N -
1){
if (r < L || R < l) return 0LL; /**
int m = (l + r)/2; * Description: DP with Binary Search
if (L <= l && r <= R) return SEG[cur].val; */
return query(LFT[cur], L, R, l, m) +
query(RGT[cur], L, R, m + 1, r); vi bes = {0};
} int n;
8. STRINGS (3) 20
/**
7.1.4 String Removals * Source: Own
* Usage: CEOI 2004 Two Sawmills
*/
/**
* Description: DP eliminates overcounting void divi(int lo, int hi, int L, int R) {
* Verification: https://cses.fi/problemset/task/1149/ if (lo > hi) return;
*/
int mid = (lo+hi)/2;
int distinct(string S) { pair<ll,int> tmp = {1e18,-1};
vi tot(26); FOR(i,max(mid+1,L),R+1)
int ans = 1; tmp = min(tmp,{calc(0,mid)+calc(mid+1,i)
for (char c: S) { +calc(i+1,n),i});
int t = (ans-tot[c-’a’]+MOD)%MOD; ans = min(ans,tmp.f);
tot[c-’a’] = (tot[c-’a’]+t)%MOD;
ans = (ans+t)%MOD; divi(lo,mid-1,L,tmp.s);
} divi(mid+1,hi,tmp.s,R);
return ans; }
}
ll modpow(ll b, ll p) { tri() {
return !p?1:modpow(b*b%MOD,p/2)*(p&1?b:1)%MOD; memset(trie,0,sizeof trie);
} }
for (int stp = 1, cnt = 1; cnt < N; stp ++, 8.4 Z (5)
cnt *= 2) {
P.pb(vi(N)); 8.4.1 Aho-Corasick
F0R(i,N) L[i] = {P[stp-1][i],i+cnt < N ?
P[stp-1][i+cnt] : -1,i}; /**
sort(all(L)); * Source: https://ideone.com/0cMjZJ
// bucket_sort(); * Usage: Kattis stringmultimatching
F0R(i,N) { */
if (i && mp(L[i][0],L[i][1]) ==
mp(L[i-1][0],L[i-1][1])) template<int SZ> struct Aho {
P[stp][L[i][2]] = P[stp][L[i-1][2]]; int link[SZ], dict[SZ], sz = 1, num = 0;
else P[stp][L[i][2]] = i; vector<pii> ind[SZ];
} map<char,int> to[SZ];
} vi oc[SZ];
queue<int> q;
idx.resize(N);
F0R(i,sz(P.back())) idx[P.back()[i]] = i; Aho() {
} memset(link,0,sizeof link);
memset(dict,0,sizeof dict);
int lcp(int x, int y) { }
int res = 0;
if (x == y) return N-x; void add(string s) {
for (int k = sz(P) - 1; k >= 0 && x < N && y < int v = 0;
N; k--) { for(auto c: s) {
if (P[k][x] == P[k][y]) { if (!to[v].count(c)) to[v][c] = sz++;
x += 1 << k; v = to[v][c];
y += 1 << k; }
res += 1 << k; dict[v] = v; ind[v].pb({++num,sz(s)});
} }
}
return res; void push_links() {
} link[0] = -1; q.push(0);
}; while (sz(q)) {
int v = q.front(); q.pop();
for (auto it: to[v]) {
8. STRINGS (3) 23
/**
* Source: http://codeforces.com/blog/entry/12143
9. TREES (4) 24
int main() {
/**
vi x = z("abcababcabcaba");
* Description: offline subtree queries in O(Nlog^2N)
for (int i: x) cout << i << " ";
* Verification: January Easy 2018 - Shubham & Tree 1
cout << "\n";
*/
x = get("abcab","uwetrabcerabcab");
const int MX = 200001;
for (int i: x) cout << i << " ";
}
struct HeavyLightSet {
int loc[MX], sub[MX], par[MX], val[MX];
vi child[MX];
map<int,int> dat[MX];
9 Trees (4)
void comb(int a, int b) {
9.1 Tree Diameter int A = loc[a], B = loc[b];
if (sz(dat[A]) < sz(dat[B])) swap(a,b),
swap(A,B);
/**
for (auto& x: dat[B]) dat[A][x.f] += x.s;
* Might not be obvious why this works!
dat[B].clear(); loc[b] = A;
* Verification: http://www.spoj.com/problems/PT07Z/
}
*/
void process(int ind) {
const int MX = 10001;
sub[ind] = 1; loc[ind] = ind;
dat[ind][val[ind]] ++;
int n, dist[MX];
for (int i: child[ind]) {
vi adj[MX];
process(i);
comb(i,ind);
void dfs(int cur, int pre) {
sub[ind] += sub[i];
for (int i: adj[cur]) if (i != pre) {
}
dist[i] = dist[cur]+1;
// now do stuff with values
dfs(i,cur);
}
}
};
}
9. TREES (4) 25
/**
9.3 Advanced * Source: http://codeforces.com/blog/entry/22072
* Dependency: Lazy SegTree
9.3.1 Centroid Decomposition * Verification: USACO Grass Planting
*/
/**
vector<vi> graph;
* Source: own
* Verification Problem: Ciel and Commander
template <int V> struct HeavyLight { // sum queries,
(http://codeforces.com/contest/321/problem/C)
sum updates
* Code:
int parent[V], heavy[V], depth[V];
http://codeforces.com/contest/321/submission/33952270
int root[V], treePos[V];
*/
LazySegTree<V> tree;
const int MX = 100001;
void init() {
int n = graph.size();
int N, visit[MX], sub[MX], par[MX];
FOR(i,1,n+1) heavy[i] = -1;
vi adj[MX];
parent[1] = -1, depth[1] = 0;
dfs(1);
void dfs (int no) {
for (int i = 1, currentPos = 0; i <= n; ++i)
sub[no] = 1;
if (parent[i] == -1 || heavy[parent[i]]
for (int i: adj[no]) if (!visit[i] && i !=
!= i)
par[no]) {
for (int j = i; j != -1; j =
par[i] = no;
heavy[j]) {
dfs(i);
root[j] = i;
sub[no] += sub[i];
treePos[j] = currentPos++;
}
}
}
}
int get_centroid(int x) {
int dfs(int v) {
par[x] = 0;
int size = 1, maxSubtree = 0;
dfs(x);
for (auto u : graph[v]) if (u != parent[v]) {
int sz = sub[x];
parent[u] = v;
while (1) {
depth[u] = depth[v] + 1;
pii mx = {0,0};
int subtree = dfs(u);
for (int i: adj[x]) if (!visit[i] && i !=
if (subtree > maxSubtree) heavy[v] = u,
par[x]) mx = max(mx,{sub[i],i});
maxSubtree = subtree;
if (mx.f*2 > sz) x = mx.s;
size += subtree;
else return x;
}
}
return size;
}
}
void solve (int x) {
template <class BinaryOperation>
x = get_centroid(x); visit[x] = 1;
void processPath(int u, int v, BinaryOperation op)
// do stuff
{
cout << x << "\n";
for (; root[u] != root[v]; v =
for (int i: adj[x]) if (!visit[i]) solve(i);
parent[root[v]]) {
}
if (depth[root[u]] > depth[root[v]])
swap(u, v);
int main() {
op(treePos[root[v]], treePos[v]);
cin >> N;
}
F0R(i,N-1) {
if (depth[u] > depth[v]) swap(u, v);
int a,b; cin >> a >> b;
op(treePos[u]+1, treePos[v]); // assumes
adj[a].pb(b), adj[b].pb(a);
values are stored in edges, not vertices
}
}
solve(1);
}
void modifyPath(int u, int v, int value) {
processPath(u, v, [this, &value](int l, int r)
{ tree.upd(l, r, value); });
10. MATH (4) 27
void process(ll a, ll n) {
10.1.2 Phi vector<pii> z;
for (int i = 2; i*i <= n; ++i) if (n % i == 0)
{
/** int co = 0;
10. MATH (4) 28
while (n % i == 0) n /= i, co++; }
z.pb({i,co});
} mat operator*(const mat& m) {
if (n != 1) z.pb({n,1}); mat<SZ> a;
for (auto A: z) { F0R(i,SZ) F0R(j,SZ) F0R(k,SZ)
if (M.count(A.f)) { a.d[i][k] = (a.d[i][k]+d[i][j]*m.d[j][k]) %
pii p1 = M[A.f]; MOD;
pii p2 = {A.s,a%(ll)pow(A.f,A.s)}; return a;
if (p1 > p2) swap(p1,p2); }
if (p2.s%(ll)pow(A.f,p1.f) != p1.s) bad
= 1; mat operator^(ll p) {
M[A.f] = p2; mat<SZ> a, b(*this);
} else M[A.f] = {A.s,a%(ll)pow(A.f,A.s)}; F0R(i,SZ) a.d[i][i] = 1;
}
} while (p) {
if (p&1) a = a*b;
ll po(ll b, ll p) { b = b*b;
ll z = 1; p /= 2;
F0R(i,p) z *= b; }
return z;
} return a;
}
pll solve(ll aa, ll nn, ll bb, ll mm) {
bad = 0, M.clear(); void print() {
a = aa, n = nn, b = bb, m = mm; F0R(i,SZ) {
process(a,n), process(b,m); F0R(j,SZ) cout << d[i][j] << " ";
if (bad) { cout << "\n";
cout << "NIE"; }
exit(0); cout << "------------\n";
} }
ll a1 = 0, a2 = 1; };
for (auto& x: M) {
a1 = naive(a2,po(x.f,x.s.f),a1,x.s.s); /*
a2 *= po(x.f,x.s.f); mat<2> x; x.d[0][0] = 1, x.d[1][0] = 2, x.d[1][1] = 1,
} x.d[0][1] = 3;
return {a1,a2}; mat<2> y = x*x;
} mat<2> z = x^5;
}; x.print(), y.print(), z.print();
*/
10.2 Matrices
10.2.2 Gaussian Elimination (6)
10.2.1 Matrix Exponentiation
/**
/** * Description: Gaussian Elimination
* Source: KACTL * Usage:
* Verification: https://dmoj.ca/problem/si17c1p5 https://open.kattis.com/problems/equationsolverplus
*/ */
F0R(i,n) {
F0R(j,n+1) cout << a[i][j] << " "; template<int SZ> struct Combo {
cout << "\n"; ll fac[SZ+1], ifac[SZ+1];
}
cout << "----\n"; Combo() {
} fac[0] = ifac[0] = 1;
FOR(i,1,SZ+1) {
void solve() { fac[i] = i*fac[i-1] % MOD;
mat a(n); F0R(i,n) a[i].resize(n+1); ifac[i] = inv(fac[i]);
F0R(i,n) F0R(j,n) cin >> a[i][j]; }
F0R(i,n) cin >> a[i][n]; }
int done[n]; F0R(i,n) done[i] = -1;
ll po (ll b, ll p) {
F0R(i,n) { return !p?1:po(b*b%MOD,p/2)*(p&1?b:1)%MOD;
F0R(j,n) if (done[j] == -1 && abs(a[j][i]) > }
EPS) {
ld t = a[j][i]; ll inv (ll b) { return po(b,MOD-2); }
F0R(k,n+1) a[j][k] /= t;
ll comb(ll a, ll b) {
F0R(k,n) if (j != k) elim(a,i,j,k); if (a < b) return 0;
done[j] = i; break; ll tmp = fac[a]*ifac[b] % MOD;
} tmp = tmp*ifac[a-b] % MOD;
} return tmp;
}
int num = 0; };
F0R(i,n) if (done[i] == -1) {
num ++;
if (abs(a[i][n]) > EPS) {
10.3.2 Combo Plus
cout << "inconsistent\n";
return;
} /**
} * Description: Extends combo to a power of a prime
ld ans[n]; F0R(i,n) ans[i] = * Verification: https://dmoj.ca/problem/tle17c4p5
numeric_limits<double>::max(); */
F0R(i,n) if (done[i] != -1) {
bool bad = 0; typedef pair<ll,ll> pll;
F0R(j,n) if (j != done[i] && abs(a[i][j]) >
EPS) { template<int SZ> struct ComboExtended {
bad = 1; pll fac[SZ+1], ifac[SZ+1], mod;
break; ll MOD = 1;
}
if (!bad) ans[done[i]] = a[i][n]; void init(pll _mod) { // prime, power
} mod = _mod; F0R(i,mod.s) MOD *= mod.f;
F0R(i,n) {
if (ans[i] != numeric_limits<double>::max()) fac[0] = ifac[0] = {1,0};
cout << ans[i]; FOR(i,1,SZ+1) {
else cout << "?"; fac[i] = fac[i-1];
cout << " "; int I = i, z = 0;
} while (I % mod.f == 0) I /= mod.f, z++;
cout << "\n"; fac[i].f = fac[i].f*I%MOD; fac[i].s += z;
} ifac[i] = {inv(fac[i].f,MOD),fac[i].s};
}
}
return a;
ll comb(ll a, ll b) { }
if (a < b) return 0;
ll tmp = (fac[a].f*ifac[b].f%MOD)*ifac[a-b].f vd orConv(vd a, vd b) {
% MOD; int s = max(sz(a),sz(b)), L = get(s), n = 1<<L;
ll z = fac[a].s-fac[b].s-fac[a-b].s; if (s <= 0) return {};
if (z >= mod.s) return 0;
F0R(i,z) tmp = tmp*mod.f % MOD; a.resize(n); reverse(all(a)); a = andConv(a);
return tmp; b.resize(n); reverse(all(b)); b = andConv(b);
}
}; F0R(i,n) a[i] = a[i]*b[i];
a = andConv(a,1);
reverse(all(a));
10.4 FFT (6) return a;
}
10.4.1 And Convolution
vl orConv(vl a, vl b) {
/** vd A; for (ll x: a) A.pb(x);
* Description: Similar to FWHT vd B; for (ll x: b) B.pb(x);
* Source: CSA - FFT And Variations vd c = orConv(A,B);
*/ vl C; for (double x: c) C.pb(round(x));
return C;
typedef vector<double> vd; }
typedef vector<ll> vl;
vl conv(vl a, vl b) {
int get(int s) { vd A; for (ll x: a) A.pb(x);
return s > 1 ? 32 - __builtin_clz(s - 1) : 0; vd B; for (ll x: b) B.pb(x);
} vd c = conv(A,B);
vl C; for (double x: c) C.pb(round(x));
namespace andConv { return C;
vd andConv(vd P, bool inv = 0) { }
for (int len = 1; 2 * len <= sz(P); len <<= 1) }
{
for (int i = 0; i < sz(P); i += 2 * len) {
for (int j = 0; j < len; j++) {
10.4.2 Base Conversion
double u = P[i + j];
double v = P[i + len + j];
/**
if (!inv) { * Description: NTT Application
P[i + j] = v; * Usage: 2017 VT HSPC - Alien Codebreaking
P[i + len + j] = u + v; */
} else {
P[i + j] = -u + v; // NTT template
P[i + len + j] = u;
} struct Base {
} vl po10[21];
} const int base = 27;
}
Base() {
return P; po10[0] = {10};
} FOR(i,1,21) {
po10[i] = NTT::conv(po10[i-1],po10[i-1]);
vd conv(vd a, vd b) { normalize(po10[i]);
int s = max(sz(a),sz(b)), L = get(s), n = 1<<L; }
if (s <= 0) return {}; }
} int t = 2*k%n+j;
while (sz(x) && !x.back()) x.pop_back(); RES[k+j] = res[t]+roots[k]*res[t+inc];
} }
swap(res,RES);
vl convert(vl in) { }
if (sz(in) == 1) return in;
vl l = return res;
convert(vl(in.begin(),in.begin()+sz(in)/2)); }
vl r =
convert(vl(in.begin()+sz(in)/2,in.end())); vcd fft_rev(vcd& a) {
vcd res = fft(a);
r = NTT::conv(r,po10[get(sz(in))-1]); F0R(i,sz(res)) res[i] /= a.size();
normalize(r); reverse(res.begin() + 1, res.end());
return res;
int z = max(sz(l),sz(r)); }
r.resize(z);
F0R(i,sz(l)) r[i] += l[i]; vcd brute(vcd& a, vcd& b) {
normalize(r); vcd c(sz(a)+sz(b)-1);
return r; F0R(i,sz(a)) F0R(j,sz(b)) c[i+j] += a[i]*b[j];
} return c;
}; }
a.resize(s);
return a;
10.4.3 FFT
}
/** vl convll(vl a, vl b) {
* Sources: KACTL, https://pastebin.com/3Tnj5mRu vcd A(sz(a)); F0R(i,sz(a)) A[i] = a[i];
* Verification: SPOJ polymul vcd B(sz(b)); F0R(i,sz(b)) B[i] = b[i];
*/ vcd X = conv(A,B);
vl x(sz(X)); F0R(i,sz(X)) x[i] =
typedef complex<double> cd; round(X[i].real());
typedef vector<cd> vcd; return x;
typedef vector<ll> vl; }
}
int get(int s) {
return s > 1 ? 32 - __builtin_clz(s - 1) : 0; int main() {
} int T; cin >> T;
F0R(i,T) {
namespace FFT { int N; cin >> N;
vcd fft(vcd& a) { vl a(N+1), b(N+1);
int n = a.size(), x = get(n); F0R(j,N+1) cin >> a[N-j];
vcd res, RES(n), roots(n); F0R(j,N+1) cin >> b[N-j];
F0R(i,n) roots[i] = vl x = FFT::convll(a,b);
cd(cos(2*M_PI*i/n),sin(2*M_PI*i/n)); F0Rd(j,sz(x)) cout << x[j] << " ";
cout << "\n";
res = a; }
FOR(i,1,x+1) { }
int inc = n>>i;
F0R(j,inc) for (int k = 0; k < n; k += inc)
{
10. MATH (4) 32
* Code: https://pastebin.com/VJxTvEg1
queue<int> todo; todo.push(SC); */
while (todo.size()) {
if (flow[SNC]) break; struct Edge {
int x = todo.front(); todo.pop(); int v;
for (auto a: adj[x]) if (!flow[a.v] && ll flow, C;
a.flow < a.C) { int rev;
pre[a.v] = {x,a.rev}; };
flow[a.v] = min(flow[x],a.C-a.flow);
todo.push(a.v); template<int SZ> struct Dinic {
} int level[SZ], start[SZ];
} vector<Edge> adj[SZ];
enqueue(v);
while (bfs(s, t)) { }
F0R(i,SZ) start[i] = 0; }
while (ll flow = sendFlow(s, INT_MAX, t))
total += flow; void relabel (int v) {
} count[dist[v]] --; dist[v] = SZ;
for (auto e: adj[v]) if (e.C > e.flow) dist[v]
return total; = min(dist[v], dist[e.v] + 1);
} count[dist[v]] ++;
}; enqueue(v);
}
void discharge(int v) {
11.2.4 Push-Relabel (5)
for (auto &e: adj[v]) {
if (excess[v] > 0) push(v,e);
/** else break;
* Source: http://codeforces.com/blog/entry/14378 }
* Verification: SPOJ fastflow if (excess[v] > 0) {
*/ if (count[dist[v]] == 1) gap(dist[v]);
else relabel(v);
struct Edge { }
int v; }
ll flow, C;
int rev; ll maxFlow (int s, int t) {
}; for (auto &e: adj[s]) excess[s] += e.C;
void reweight() {
F0R(i,SZ) {
for (auto& p: adj[i]) p.cost += 11.3 Tarjan BCC
cost[i]-cost[p.v];
}
} /**
* Source: GeeksForGeeks (corrected)
bool spfa() { * Verification: USACO December 2017, Push a Box
F0R(i,SZ) cost[i] = MOD, num[i] = 0; * Code: https://pastebin.com/yUWuzTH8
cost[SC] = 0, num[SC] = MOD; */
priority_queue<pii,vector<pii>,greater<pii>>
todo; todo.push({0,SC}); template<int SZ> struct BCC {
int N, ti = 0;
while (todo.size()) { vi adj[SZ];
pii x = todo.top(); todo.pop(); int disc[SZ], low[SZ], comp[SZ], par[SZ];
if (x.f > cost[x.s]) continue; vector<vector<pii>> fin;
for (auto a: adj[x.s]) if (x.f+a.cost < vector<pii> st;
cost[a.v] && a.flow < a.C) {
pre[a.v] = {x.s,a.rev}; void addEdge(int u, int v) {
cost[a.v] = x.f+a.cost; adj[u].pb(v), adj[v].pb(u);
num[a.v] = min(a.C-a.flow,num[x.s]); }
todo.push({cost[a.v],a.v});
} void BCCutil(int u) {
} disc[u] = low[u] = ti++;
int child = 0;
ccost += cost[SNC];
return num[SNC] > 0; for (int i: adj[u]) if (i != par[u]) {
} if (disc[i] == -1) {
child ++; par[i] = u;
void backtrack() { st.pb({u,i});
flo += num[SNC], ans += (ll)num[SNC]*ccost; BCCutil(i);
for (int x = SNC; x != SC; x = pre[x].f) { low[u] = min(low[u],low[i]);
adj[x][pre[x].s].flow -= num[SNC];
int t = adj[x][pre[x].s].rev; if ((disc[u] == 0 && child > 1) ||
adj[pre[x].f][t].flow += num[SNC]; (disc[u] != 0 && disc[u] <=
} low[i])) { // articulation point!
} vector<pii> tmp;
while (st.back() != mp(u,i))
pii mincostflow(int sc, int snc) { tmp.pb(st.back()),
SC = sc, SNC = snc; st.pop_back();
flo = ans = ccost = 0; tmp.pb(st.back()), st.pop_back();
fin.pb(tmp);
spfa(); }
while (1) { } else if (disc[i] < disc[u]) {
reweight(); low[u] = min(low[u],disc[i]);
if (!spfa()) return {flo,ans}; st.pb({u,i});
backtrack(); }
} }
} }
};
void bcc() {
mcf<100> m; FOR(i,1,N+1) par[i] = disc[i] = low[i] = -1;
FOR(i,1,N+1) if (disc[i] == -1) {
int main() { BCCutil(i);
m.addEdge(0, 1, 16, 5); if (sz(st)) fin.pb(st);
m.addEdge(1, 2, 13, 7); st.clear();
m.addEdge(1, 2, 13, 8); }
}
pii x = m.mincostflow(0,2); };
cout << x.f << " " << x.s;
}
12. GEOMETRY (4) 37
pii A,B,C,D;
12.1.4 Point in Polygon (5)
pdd operator*(int x, pdd y) {
return {x*y.f,x*y.s}; /**
} * Source: own
* Usage:
pdd operator/(pdd y, int x) { https://open.kattis.com/problems/pointinpolygon
return {y.f/x,y.s/x}; */
}
int n,m;
pdd operator+(pdd l, pdd r) { pii p[1000];
return {l.f+r.f,l.s+r.s};
} int area(pii x, pii y, pii z) {
return (y.f-x.f)*(z.s-x.s)-(y.s-x.s)*(z.f-x.f);
int sgn(pii a, pii b, pii c) { }
return (b.s-a.s)*(c.f-a.f)-(b.f-a.f)*(c.s-a.s);
} bool on(pii x, pii y, pii z) {
if (area(x,y,z) != 0) return 0;
pdd get(pii a, pii b, pii c, pii d) { return min(x,y) <= z && z <= max(x,y);
return (abs(sgn(a,b,c))*d+abs(sgn(a,b,d))*c) }
/(abs(sgn(a,b,c))+abs(sgn(a,b,d)));
} double get(pii x, pii y, int z) {
return double((z-x.s)*y.f+(y.s-z)*x.f)/(y.s-x.s);
void solve() { }
cin >> A.f >> A.s >> B.f >> B.s >> C.f >> C.s >>
D.f >> D.s; void test(pii z) {
if (A > B) swap(A,B); int ans = 0;
if (C > D) swap(C,D); F0R(i,n) {
12. GEOMETRY (4) 39
cd tmp = (b.f-a.f)/d;
if (x == 0) return a.f+tmp*a.s*polar(1.0,theta);
12.1.5 3D Geometry (6)
return a.f+tmp*a.s*polar(1.0,-theta);
}
/**
* Description: Basic 3D Geometry double arc(circle x, cd a, cd b) {
* Usage: AMPPZ 2011 Cross Spider cd d = (a-x.f)/(b-x.f);
*/ return x.s*acos(d.real());
}
typedef vector<ll> vl;
bool on (circle x, cd y) {
typedef long double ld; return norm(y-x.f) == x.s*x.s;
}
int n;
vector<vl> cur; int main() {
cout << intersect({0,2},{1,1}) << "\n";
vl operator-(vl a, vl b) { cout << arc({0,1},cd(1,0),cd(0,1)) << "\n";
vl c(sz(a)); F0R(i,sz(a)) c[i] = a[i]-b[i]; cout << on({0,1},1) << "\n";
return c; }
}
bool ismult(vl b, vl c) {
if ((ld)b[0]*c[1] != (ld)b[1]*c[0]) return 0; 12.2 Sweep Line
if ((ld)b[0]*c[2] != (ld)b[2]*c[0]) return 0;
12.2.1 Convex Hull
if ((ld)b[2]*c[1] != (ld)b[1]*c[2]) return 0;
return 1;
} /**
* Source: Wikibooks
bool collinear(vl a, vl b, vl c) { * Usage: https://open.kattis.com/problems/convexhull
b = b-a, c = c-a; */
return ismult(b,c);
} ll cross(pii O, pii A, pii B) {
return (ll)(A.f-O.f)*(B.s-O.s)
vl cross(vl a, vl b) { -(ll)(A.s-O.s)*(B.f-O.f);
return {a[1]*b[2]-a[2]*b[1], }
a[2]*b[0]-a[0]*b[2],
a[0]*b[1]-a[1]*b[0]}; vector<pii> convex_hull(vector<pii> P) {
}
12. GEOMETRY (4) 40
sort(P.begin(),P.end()); }
P.erase(unique(P.begin(),P.end()),P.end());
if (P.size() == 1) return P; pair<double,pair<pdd,pdd>> strip(vector<pdd> v, double
di) {
int n = P.size(); pair<double,pair<pdd,pdd>> ans = MN;
F0R(i,v.size()) FOR(j,i+1,v.size()) {
vector<pii> bot = {P[0]}; if (v[i].s+di <= v[j].s) break;
FOR(i,1,n) { ans = min(ans,{dist(v[i],v[j]),{v[i],v[j]}});
while (bot.size() > 1 && }
cross(bot[bot.size()-2], bot.back(), P[i]) return ans;
<= 0) bot.pop_back(); }
bot.pb(P[i]);
} pair<double,pair<pdd,pdd>> bes (vector<pdd> v) {
bot.pop_back(); if (v.size() == 1) return MN;
int M = v.size()/2;
vector<pii> up = {P[n-1]}; vector<pdd> v1(v.begin(),v.begin()+M),
F0Rd(i,n-1) { v2(v.begin()+M,v.end());
while (up.size() > 1 && cross(up[up.size()-2], auto a = bes(v1), b = bes(v2);
up.back(), P[i]) <= 0) up.pop_back(); double di = min(a.f,b.f);
up.pb(P[i]);
} vector<pdd> V;
up.pop_back(); F0R(i,v.size()) if (v[i].f > v[M].f-di && v[i].f <
v[M].f+di) V.pb(v[i]);
bot.insert(bot.end(),all(up)); sort(V.begin(),V.end(),cmp);
return bot;
} auto z = strip(V,di);
return min(min(a,b),z);
int main() { }
int n;
while (cin >> n) { int main() {
if (n == 0) break; cout << fixed << setprecision(2);
vector<pii> P(n); F0R(i,n) cin >> P[i].f >> while (cin >> n) {
P[i].s; if (n == 0) break;
vector<pii> hull = convex_hull(P); vector<pdd> v(n);
F0R(i,n) cin >> v[i].f >> v[i].s;
cout << hull.size() << "\n"; sort(v.begin(),v.end());
for (auto a: hull) cout << a.f << " " << a.s auto a = bes(v);
<< "\n"; cout << a.s.f.f << " " << a.s.f.s << " " <<
} a.s.s.f << " " << a.s.s.s << "\n";
} }
}
invy[i] = inv(t);
t = t*cur%MOD;
}
ll x; cin >> x;
cout << query(x) << "\n";
}
/**
* Source: Misc solutions to CF Nagini
* Description: 10^{10} operations are ok!
* Passes the occasional disgusting CF task
* Also see "Welcome home, Chtholly"
*/
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> q;
F0R(i,100001) mx[i] = -MOD, mn[i] = MOD;
F0R(i,q) {
int t,l,r,k; cin >> t >> l >> r;
r -= l;