-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
64 changed files
with
3,749 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// MO algorithm | ||
|
||
// Description: | ||
// Answers queries offline with sqrt decomposition. | ||
// Complexity: | ||
// exec - O(n*sqrt(n)*O(remove / add)) | ||
const int magic = 230; | ||
|
||
struct Query { | ||
int l, r, idx; | ||
Query () {} | ||
Query (int _l, int _r, int _idx) : l(_l), r(_r), idx(_idx) {} | ||
bool operator < (const Query &o) const { | ||
return mp(l / magic, r) < mp(o.l / magic, o.r); | ||
} | ||
}; | ||
|
||
struct MO { | ||
int sum; | ||
MO(vector<ll> &v) : sum(0), v(v), cnt(N), C(N) {} | ||
|
||
void exec(vector<Query> &queries, vector<ll> &answers) { | ||
answers.resize(queries.size()); | ||
sort(queries.begin(), queries.end()); | ||
|
||
int cur_l = 0; | ||
int cur_r = -1; | ||
|
||
for (Query q : queries) { | ||
while (cur_l > q.l) { | ||
cur_l--; | ||
add(cur_l); | ||
} | ||
while (cur_r < q.r) { | ||
cur_r++; | ||
add(cur_r); | ||
} | ||
while (cur_l < q.l) { | ||
remove(cur_l); | ||
cur_l++; | ||
} | ||
while (cur_r > q.r) { | ||
remove(cur_r); | ||
cur_r--; | ||
} | ||
answers[q.idx] = get_answer(cur_l, cur_r); | ||
} | ||
} | ||
|
||
void add(int i) { | ||
sum += v[i]; | ||
} | ||
|
||
void remove(int i) { | ||
sum -= v[i]; | ||
} | ||
|
||
ll get_answer(int l, int r) { | ||
return sum; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Binary Indexed Tree | ||
|
||
// !! zero indexed !! | ||
// all operations are O(logN) | ||
|
||
template<typename T> struct Bit { | ||
vector<T> bit; | ||
Bit(int n): bit(n) {} | ||
|
||
void update(int id, T val) { | ||
for(id+=1; id<=int(bit.size()); id+=id&-id) | ||
bit[id-1] += val; | ||
} | ||
|
||
T query(int id) { | ||
T sum = T(); | ||
for(id+=1; id>0; id-=id&-id) | ||
sum += bit[id-1]; | ||
return sum; | ||
} | ||
|
||
// returns the first prefix for which sum of 0..=pos >= val | ||
// returns bit.size() if such prefix doesnt exists | ||
// it is necessary that v[i] >= 0 for all i for monotonicity | ||
int lower_bound(T val) { | ||
T sum = T(); | ||
int pos = 0; | ||
int logn = 31 - __builtin_clz(bit.size()); | ||
for(int i=logn;i>=0;i--) { | ||
int nxt = pos + (1<<i); | ||
if(nxt <= int(bit.size()) | ||
&& sum + bit[nxt - 1] < val) { | ||
sum += bit[nxt - 1]; | ||
pos = nxt; | ||
} | ||
} | ||
return pos; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Binary Indexed Tree 2D | ||
|
||
// 0-indexed | ||
// update(x, y, val): m[row][col] += val | ||
// query(x, y): returns sum m[0..=x][0..=y] | ||
template <typename T> struct Bit2D { | ||
int n, m; | ||
vector<T> bit; | ||
Bit2D(int _n, int _m): n(_n), m(_m), bit(n*m) {} | ||
|
||
T query(int x, int y) { | ||
T res = 0; | ||
for(x+=1;x>0;x-=x&-x) | ||
for(int z=y+1;z>0;z-=z&-z) | ||
res += bit[(x-1)*m+z-1]; | ||
return res; | ||
} | ||
|
||
void update(int x, int y, T val) { | ||
for(x+=1;x<=n;x+=x&-x) | ||
for(int z=y+1;z<=m;z+=z&-z) | ||
bit[(x-1)*m+z-1] += val; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// Implicit Lazy Treap | ||
|
||
// All operations are O(log N) | ||
// If changes need to be made in lazy propagation, | ||
// See Node::push() | ||
// To extend behavior of Treap, use inheritance | ||
// | ||
// Important functions: | ||
// Treap::insert(int ind, T info) | ||
// Treap::erase(int ind) | ||
// Treap::reverse(int l, int r) | ||
// Treap::operator[](int ind) | ||
|
||
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); | ||
|
||
template <typename ND, typename T = typename ND::T> | ||
struct Treap { | ||
ND *root; | ||
vector<ND> v; | ||
// max: maximum number of NDs created | ||
Treap(int max): root(0) { | ||
v.reserve(max); | ||
} | ||
ND* new_node(T info) { | ||
// assert(v.size() != v.capacity()); | ||
v.emplace_back(info); | ||
return &v.back(); | ||
} | ||
int getl(ND& nd) { | ||
return nd.l ? nd.l->sz : 0; | ||
} | ||
void merge(ND* l, ND* r, ND*& res) { | ||
if(!l || !r) { | ||
res = l ? l : r; | ||
return; | ||
} | ||
l->push(); r->push(); | ||
if(l->h > r->h) { | ||
res = l; | ||
merge(l->r, r, l->r); | ||
} else { | ||
res = r; | ||
merge(l, r->l, r->l); | ||
} | ||
res->pull(); | ||
} | ||
// left treap has size pos | ||
void split(ND* x, ND*& l, ND*& r, int pos, int ra = 0) { | ||
if(!x) { | ||
l = r = 0; | ||
return; | ||
} | ||
x->push(); | ||
int nra = ra + getl(*x) + 1; | ||
if(pos < nra) { | ||
split(x->l, l, r, pos, ra); | ||
x->l = r; | ||
r = x; | ||
} else { | ||
split(x->r, l, r, pos, nra); | ||
x->r = l; | ||
l = x; | ||
} | ||
x->pull(); | ||
} | ||
// Merges all s and makes them root | ||
template <int SZ> | ||
void merge(array<ND*, SZ> s) { | ||
root = 0; | ||
for(ND* nd: s) | ||
merge(root, nd, root); | ||
} | ||
// Splits root into SZ EXCLUSIVE intervals | ||
// [0..s[0]), [s[0]..s[1]), [s[1]..s[2])... [s[SZ-1]..end) | ||
// Example: split<3>({l, r}) gets the exclusive interval [l, r) | ||
template <int SZ> | ||
array<ND*, SZ> split(array<int, SZ-1> s) { | ||
assert(s.back() <= (root ? root->sz : 0)); | ||
array<ND*, SZ> res; | ||
split(root, res[0], res[1], s[0]); | ||
for(int i=1;i<SZ-1;i++) | ||
split(res[i], res[i], res[i+1], s[i]-s[i-1]); | ||
root = 0; | ||
return res; | ||
} | ||
void insert(int ind, T info) { | ||
auto s = split<2>({ind}); | ||
merge<3>({s[0], new_node(info), s[1]}); | ||
} | ||
void erase(int ind) { | ||
auto s = split<3>({ind, ind+1}); | ||
merge<2>({s[0], s[2]}); | ||
} | ||
T operator[](int ind) { | ||
assert(0 <= ind && ind < root->sz); | ||
ND* x = root; | ||
x->push(); | ||
for(int ra = 0, nra = getl(*x); nra != ind; nra = ra + getl(*x)) { | ||
if(nra < ind) ra = nra + 1, x = x->r; | ||
else x = x->l; | ||
x->push(); | ||
} | ||
return x->info; | ||
} | ||
}; | ||
|
||
struct Node { | ||
using T = int; | ||
T info; | ||
Node *l, *r; | ||
int sz; | ||
uint64_t h; | ||
// more fields here - example: reverse interval | ||
bool rev; | ||
Node(T i): info(i), l(0), r(0), sz(1), h(rng()), rev(false) {} | ||
void push() { | ||
// example: reverse interval | ||
if(rev) { | ||
swap(l, r); | ||
for(auto c: {l, r}) | ||
if(c) c->rev = !c->rev; | ||
rev = false; | ||
} | ||
} | ||
void pull() { | ||
sz = 1; | ||
for(auto c: {l, r}) | ||
if(c) sz += c->sz; | ||
} | ||
}; | ||
|
||
struct MyTreap : Treap<Node> { | ||
MyTreap(int max): Treap<Node>(max) {} | ||
// new methods here - example: reverse interval | ||
void reverse(int l, int r) { | ||
auto s = split<3>({l, r+1}); | ||
s[1]->rev = !s[1]->rev; | ||
merge<3>(s): | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Linked Linked | ||
// | ||
// Parameters: | ||
// CAP: How many nodes can be created at most | ||
// T: What type to be stored in a node in the linked list | ||
// | ||
// Functions: | ||
// append(T info): puts node with info in the tail | ||
// remove(Node* nd): removes node in O(1) | ||
// | ||
// Tested: https://codeforces.com/contest/1181/submission/246289459 | ||
namespace linked_list { | ||
constexpr int CAP = 10'000'000; | ||
using T = int; | ||
|
||
struct Node { | ||
T info; | ||
Node *prv, *nxt; | ||
}; | ||
|
||
Node arena[CAP]; | ||
int arena_cnt = 0; | ||
|
||
struct LinkedList { | ||
Node* new_node(T info) { | ||
Node* ret = arena + (arena_cnt++); | ||
ret->info = info; | ||
ret->prv = ret->nxt = 0; | ||
return ret; | ||
} | ||
|
||
Node *head, *tail; | ||
LinkedList(): head(0), tail(0) {} | ||
void append(T info) { | ||
Node* nd = new_node(info); | ||
if(!head) | ||
head = tail = nd; | ||
else { | ||
tail->nxt = nd; | ||
nd->prv = tail; | ||
tail = nd; | ||
} | ||
} | ||
void remove(Node* nd) { | ||
if(nd == head && nd == tail) | ||
head = tail = 0; | ||
else if(nd == head) | ||
head = nd->nxt, head->prv = 0; | ||
else if(nd == tail) | ||
tail = nd->prv, tail->nxt = 0; | ||
else { | ||
auto prv = nd->prv, nxt = nd->nxt; | ||
prv->nxt = nxt; | ||
nxt->prv = prv; | ||
} | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// NCE | ||
// For each i, find nearest l < i < r such that | ||
// op(l, i), op(r, i) = true if they exist | ||
// l = -1, r = v.size() otherwise | ||
// | ||
// Example: nce(v, greater<T>()): for each i returns | ||
// nce[i] = { | ||
// biggest l < i such that v[l] > v[i] | ||
// smallest r > i such that v[r] > v[i] | ||
// } | ||
// | ||
// Complexity: O(N) | ||
|
||
template <typename T, typename OP> | ||
vector<pair<int, int>> nce(vector<T> v, OP op) { | ||
int n = v.size(); | ||
vector<pair<int, int>> res(n); | ||
vector<pair<T, int>> st; | ||
for(int i=0;i<n;i++) { | ||
while(!st.empty() && !op(st.back().first, v[i])) | ||
st.pop_back(); | ||
if(st.empty()) res[i].first = -1; | ||
else res[i].first = st.back().second; | ||
st.emplace_back(v[i], i); | ||
} | ||
st.clear(); | ||
for(int i=n-1;i>=0;i--) { | ||
while(!st.empty() && !op(st.back().first, v[i])) | ||
st.pop_back(); | ||
if(st.empty()) res[i].second = n; | ||
else res[i].second = st.back().second; | ||
st.emplace_back(v[i], i); | ||
} | ||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// Ordered Set | ||
#include <ext/pb_ds/assoc_container.hpp> | ||
#include <ext/pb_ds/tree_policy.hpp> | ||
using namespace __gnu_pbds; | ||
// iterator find_by_order(size_t index), size_t order_of_key(T key) | ||
template <typename T> | ||
using ordered_set=tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// RMQ | ||
// Description: | ||
// Answers queries on a range. | ||
// Complexity: | ||
// build - O(N logN) | ||
// query - O(1) | ||
|
||
template <typename T> struct RMQ { | ||
vector<vector<T>> dp; | ||
T ops(T a, T b) { return min(a,b); } | ||
RMQ() {} | ||
RMQ(vector<T> v) { | ||
int n = v.size(); | ||
int log = 32-__builtin_clz(n); | ||
dp.assign(log, vector<T>(n)); | ||
copy(all(v), dp[0].begin()); | ||
for(int l=1;l<log;l++) for(int i=0;i<n;i++) { | ||
auto &cur = dp[l], &ant = dp[l-1]; | ||
cur[i] = ops(ant[i], ant[min(i+(1<<(l-1)), n-1)]); | ||
} | ||
} | ||
T query(int a, int b) { | ||
if(a == b) return dp[0][a]; | ||
int p = 31-__builtin_clz(b-a); | ||
auto &cur = dp[p]; | ||
return ops(cur[a], cur[b-(1<<p)+1]); | ||
} | ||
}; |
Oops, something went wrong.