Skip to content

Commit d51f1fd

Browse files
committed
Add some stuf :\
1 parent 15eed43 commit d51f1fd

File tree

6 files changed

+109
-261
lines changed

6 files changed

+109
-261
lines changed

data_structure/hld.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
const int N = 1e4 + 10; // max of nodes
2+
int n;
3+
vvii g[N]; // the tree
4+
ll nxt[N], depth[N], tt, sz[N], in[N], out[N], rin[N], p[N];
5+
int cst2[N + 10];
6+
7+
// some segment tree code here!
8+
9+
void dfs_sz(int v = 0, int par = 0, int dpth = 0) {
10+
sz[v] = 1, p[v] = par, depth[v] = dpth;
11+
for (auto &u: g[v]) {
12+
if (u.first != par) {
13+
dfs_sz(u.first, v, dpth + 1);
14+
sz[v] += sz[u.first];
15+
if (sz[u.first] > sz[g[v][0].first])
16+
swap(u, g[v][0]);
17+
}
18+
}
19+
}
20+
21+
// nxt[x] ==> head of segment which x belongs to
22+
// [in[nxt[v]], in[v]] ==> path from head of path which contains 'v' to 'v'
23+
// [in[v], out[v]) == > subtree of 'v', pay attention to right )
24+
void dfs_hld(int v = 0, int par = 0, int cst = -inf) { // change cst in case of other operations if needed
25+
in[v] = tt++;
26+
rin[in[v]] = v;
27+
28+
// modify in case of vertex query!
29+
cst2[in[v]] = cst; // setting cost of this edge(par --> v) in array which segment tree build is called upon it
30+
for (auto u: g[v]) {
31+
if (u.first != par) {
32+
nxt[u.first] = (u.first == g[v][0].first ? nxt[v] : u.first);
33+
dfs_hld(u.first, v, u.second);
34+
}
35+
}
36+
out[v] = tt;
37+
}
38+
39+
ll crawl(ll u, ll v) { // path query
40+
ll ans = -1000000000LL; // we want max of a path, so we initialize this way
41+
while (nxt[u] != nxt[v]) {
42+
if (depth[nxt[u]] < depth[nxt[v]]) swap(u, v);
43+
ans = max(ans, go(1, 0, n - 1, in[nxt[u]], in[u])); // go is get function of segment tree
44+
u = p[nxt[u]];
45+
}
46+
if (in[v] > in[u]) swap(v, u);
47+
return max(ans, go(1, 0, n - 1, in[v] + 1, in[u])); // in case of node queries remove +1 because even the head matters
48+
}
49+
50+
void modify(int a, int b) { // modify node or edge 'a' to value 'b'
51+
upd(1, 0, n - 1, in[a], b); // segment tree update
52+
}
53+
54+
int main() {
55+
// get input here ...
56+
dfs_sz();
57+
dfs_hld();
58+
build(1, 0, n - 1); // build segment tree for tree with n nodes
59+
60+
// query part:
61+
// ask query, one based
62+
int a, b; cin >> a >> b; a--, b--;
63+
cout << crawl(a, b) << endl;
64+
65+
// update a'th edge to 'b'
66+
cin >> a >> b; a--;
67+
// if query is on nodes, then just use the actual node to update
68+
int u = edges[a].first, v = edges[a].second;
69+
// we assume the node with higher depth to be representative of the edge
70+
if (depth[u] > depth[v]) modify(u, b); // depth is valued after running dfs
71+
else modify(v, b);
72+
}

data_structure/seg_tree_lazy_update.cpp

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,53 @@
11
vi arr, t, lazy; // arr is numbers to build seg tree with, if its size is 'n' then t and lazy size should be 4 * n (2 * n)
22

3-
void build(int node, int a, int b) // call build(1, 0, n - 1) for n elements
4-
{
5-
if(a>b) return;
6-
if (a==b)
7-
{
8-
t[node]=arr[a];
9-
return;
3+
void build(int node, int a, int b){ // call build(1, 0, n - 1) for n elements
4+
if(a > b) return;
5+
if (a == b){
6+
t[node] = arr[a]; return;
107
}
118

129
build(node*2, a, (a+b)/2);
1310
build(node*2+1,(a+b)/2+1,b);
1411

15-
t[node]=t[node*2]+t[node*2+1]; // update here in case of change of operation, for example min
12+
t[node] = t[node * 2] + t[node * 2+1]; // update here in case of change of operation, for example min
1613
}
1714

18-
ull query(int node, int a, int b, int i, int j) // call query(1, 0, n - 1, i, j) to get query of i..j for seg tree of n elements
19-
{
20-
if(a>b||a>j||b<i) return 0;
21-
if (lazy[node] !=0 )
22-
{
15+
ull query(int node, int a, int b, int i, int j){ // call query(1, 0, n - 1, i, j) to get query of i..j for seg tree of n elements
16+
if(a>b || a>j || b<i) return 0;
17+
if (lazy[node] !=0 ){
2318
t[node]+=lazy[node]*(b-a+1); // it is possible to update the tree in ways other that increasing a range.
2419
// for example it is possible to change all the elements of a range to a number, for example all numbers in range of i..j to 11
2520
// just underestand the way lazy works and change lazy arr value and interaction between lazy and real tree array, like t[node] = lazy[node] * (b - a + 1)
26-
if (a!=b)
27-
{
28-
lazy[node*2]+=lazy[node];
29-
lazy[node*2+1]+=lazy[node];
21+
if (a!=b){
22+
lazy[node*2] += lazy[node];
23+
lazy[node*2+1] += lazy[node];
3024
}
3125
lazy[node]=0;
3226
}
3327

34-
if (a>=i && b<=j) return t[node];
28+
if (a >= i && b <= j) return t[node];
3529

3630
ull q1=query(node*2, a, (a+b)/2, i, j);
3731
ull q2=query(node*2+1, (a+b)/2+1, b, i, j);
3832

39-
return q1+q2; // update here in case of change of operation, for example min
33+
return q1 + q2; // update here in case of change of operation, for example min
4034
}
4135

42-
void update(int node, int a, int b, int i, int j, int inc)
43-
{
44-
if(a>b) return;
45-
if (lazy[node]!=0)
46-
{
47-
t[node]+=lazy[node]*(b-a+1);
48-
if (a!=b)
49-
{
36+
void update(int node, int a, int b, int i, int j, int inc){
37+
if(a > b) return;
38+
if (lazy[node] !=0) {
39+
t[node] += lazy[node] * (b-a+1);
40+
if (a!=b) {
5041
lazy[node*2]+=lazy[node];
5142
lazy[node*2+1]+=lazy[node];
5243
}
53-
lazy[node]=0;
44+
lazy[node] = 0;
5445
}
55-
if(a>b||a>j||b<i) return;
46+
if(a>b || a>j || b<i) return;
5647

57-
if (a>=i && b<=j)
58-
{
48+
if (a >= i && b <= j){
5949
t[node]+=inc*(b-a+1);
60-
if (a!=b)
61-
{
50+
if (a!=b){
6251
lazy[node*2]+=inc;
6352
lazy[node*2+1]+=inc;
6453
}

handy-algorithms/mu.explain

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
mu[i] = {0 if i contains a prime more than once
2+
1 if i consists of even number of primes
3+
-1 otherwise, ie. odd number of primes}
4+
mu can be used to count number of things with gcd of 1 using inclution exclution
5+
to do this: sigma_over_possible_j_as_product_of_primes(mu[j] * f(j))
6+
where f(j) returns number of things where their gcd is divisible by every elemnt of j's factorization, ie. 'j'.

mathematics/number-theory.md

Lines changed: 5 additions & 216 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
# Number Theory
2-
3-
### Prime Numbers
4-
51
// Linear sieve, change it to use bitset instead
62
// runs in O(n) since it crosses the composite numbers exactly once
73
std::vector <int> prime;
@@ -18,218 +14,11 @@ void sieve (int n) {
1814
}
1915
}
2016

21-
**Sieve of Eratosthenes**: to generate list of prime numbers
22-
* O(n log log n): `n = 1e7`
23-
**Prime checker**
24-
* O(1) for `n <= sieve_size` and O(sqrt(n) / ln sqrt(n)) for bigger `n`s.
25-
26-
27-
```cpp
28-
#include <bitset>
29-
30-
ll sieve_size;
31-
bitset<10000010> bs; // 10^7 should be enough for most cases
32-
vi primes;
33-
34-
// create list of primes in [0..upperbound]
35-
void sieve(ll upperbound) {
36-
sieve_size = upperbound + 1; // add 1 to include upperbound
37-
bs.set(); // set all bits to 1
38-
bs[0] = bs[1] = 0; // except index 0 and 1
39-
for (ll i = 2; i <= sieve_size; i++)
40-
if (bs[i]) {
41-
// cross out multiples of i starting from i * i!
42-
for (ll j = i * i; j <= sieve_size; j += i) bs[j] = 0;
43-
primes.push_back(i);
44-
}
45-
}
46-
47-
bool isPrime(ll n) {
48-
if (n <= sieve_size) return bs[n];
49-
for (int i = 0; i < primes.size(); i++)
50-
if (n % primes[i] == 0) return false;
51-
return true;
52-
} // note: only work for n <= (last prime in vi "primes")^2
53-
54-
// inside main()
55-
sieve(10000000); // can go up to 10^7 (need few seconds)
56-
```
57-
58-
### GCD and LCM
59-
60-
* O(log10 n): `n = max(a, b)`
61-
62-
```cpp
63-
int gcd(int a, int b) {
64-
return b == 0 ? a : gcd(b, a % b);
65-
}
66-
int lcm(int a, int b) {
67-
return a * (b / gcd(a, b));
68-
}
69-
```
70-
71-
### Factorial
72-
73-
* O(n)
74-
75-
```cpp
76-
// ll can hold up to fact(20); for beyond use Java BigInteger
77-
ll fact(int n) {
78-
return n == 0 ? 1 : n * fact(n - 1);
79-
}
80-
```
81-
82-
### Prime-Power Factorization
83-
84-
* O(sqrt(n) / ln sqrt(n))
85-
86-
```cpp
87-
// needs sieve of eratosthenes
88-
vi primeFactors(ll n) {
89-
vi factors;
90-
ll PF_idx = 0, PF = primes[PF_idx];
91-
while (PF * PF <= n) {
92-
while (n % PF == 0) {
93-
n /= PF;
94-
factors.push_back(PF);
95-
}
96-
PF = primes[++PF_idx];
97-
}
98-
if (n != 1) factors.push_back(n); // special case if n is a prime
99-
return factors;
100-
}
101-
102-
// inside int main(), assuming sieve(1000000) has been called before
103-
vi r = primeFactors(2147483647);
104-
```
105-
106-
### Functions involving prime numbers
107-
108-
* `numPF(n)`: Count the number of prime factors of `n`
109-
11017
```cpp
111-
ll numPF(ll n) {
112-
ll PF_idx = 0, PF = primes[PF_idx], ans = 0;
113-
while (PF * PF <= n) {
114-
while (n % PF == 0) {
115-
n /= PF;
116-
ans++;
117-
}
118-
PF = primes[++PF_idx];
18+
long long gcd(long long a, long long b) {
19+
while (a > 0 && b > 0) {
20+
if (a > b) a %= b;
21+
else b %= a;
11922
}
120-
if (n != 1) ans++;
121-
return ans;
122-
}
123-
```
124-
125-
* `numDiffPF(n)`: Count the number of *different* prime factors of `n`
126-
127-
```cpp
128-
ll numDiffPF(ll n) {
129-
ll PF_idx = 0, PF = primes[PF_idx], ans = 0;
130-
while (PF * PF <= n) {
131-
int power = 0;
132-
while (n % PF == 0) {
133-
n /= PF;
134-
power++;
135-
}
136-
if (power)
137-
ans++;
138-
PF = primes[++PF_idx];
139-
}
140-
if (n != 1) ans++;
141-
return ans;
142-
}
143-
```
144-
145-
* `numDiv(n)`: Count the number of *divisors* of `n`
146-
147-
```cpp
148-
ll numDiv(ll n) {
149-
ll PF_idx = 0, PF = primes[PF_idx], ans = 1;
150-
while (PF * PF <= n) {
151-
ll power = 0;
152-
while (n % PF == 0) {
153-
n /= PF;
154-
power++;
155-
}
156-
ans *= power + 1;
157-
PF = primes[++PF_idx];
158-
}
159-
if (n != 1) ans *= 2; // last factor has pow = 1, we add 1 to it
160-
return ans;
161-
}
162-
```
163-
164-
* `sumDiv(n)`: Sum of divisors of `n`
165-
166-
```cpp
167-
ll sumDiv(ll n) {
168-
ll PF_idx = 0, PF = primes[PF_idx], ans = 1;
169-
while (PF * PF <= n) {
170-
ll power = 0;
171-
while (n % PF == 0) {
172-
n /= PF;
173-
power++;
174-
}
175-
ans *= ((ll)pow((double)PF, power + 1.0) - 1) / (PF - 1);
176-
PF = primes[++PF_idx];
177-
}
178-
if (n != 1) ans *= ((ll)pow((double)n, 2.0) - 1) / (n - 1); // last
179-
return ans;
180-
}
181-
```
182-
183-
* `EulerPhi(n)`: Count the number of positive integers < `n` that are relatively prime to `n`
184-
185-
The formula is: `phi(n) = n * PI (1 - 1/PF) for PF = prime factors of n`
186-
187-
```cpp
188-
ll EulerPhi(ll n) {
189-
ll PF_idx = 0, PF = primes[PF_idx], ans = n;
190-
while (PF * PF <= n) {
191-
if (n % PF == 0) ans -= ans / PF;
192-
while (n % PF == 0) n /= PF;
193-
PF = primes[++PF_idx];
194-
}
195-
if (n != 1) ans -= ans / n;
196-
return ans;
197-
}
198-
```
199-
200-
### Modified Sieve
201-
202-
Used when there are many numbers to determine `numDiffPF` for them
203-
204-
```cpp
205-
vi numDiffPF(MAX_N, 0);
206-
207-
for (int i = 2; i < MAX_N; i++)
208-
if (numDiffPF[i] == 0) // i is a prime number
209-
for (int j = i; j < MAX_N; j += i)
210-
numDiffPF[j]++; // increase the values of multiples of
211-
```
212-
213-
### Extended Euclid: Solving Linear Diophantine Equation
214-
215-
Suppose we have `ax + by = c` and `d = gcd(a, b)`.
216-
If `d | c` is not true then there is no integral solutions.
217-
Otherwise the first solution `(x0, y0)` can be found using **Extended Euclid**.
218-
Then other solutions can be derived from `x = x0 + (b/d)n` and `y = y0 - (a/d)n`.
219-
220-
```cpp
221-
// store x, y, and d as global variables
222-
void extendedEuclid(int a, int b) {
223-
if (b == 0) {
224-
x = 1;
225-
y = 0;
226-
d = a;
227-
return;
228-
} // base case
229-
extendedEuclid(b, a % b); // similar as the original gcd
230-
int x1 = y;
231-
int y1 = x - (a / b) * y;
232-
x = x1;
233-
y = y1;
23+
return a + b;
23424
}
235-
```

0 commit comments

Comments
 (0)