├── README.md ├── DP ├── kadane.cpp ├── Subset over Sum (sos Dp) │ ├── CF112E.cpp │ ├── Special_pairs.cpp │ └── CF225E.cpp ├── CHTPersistent.cpp └── CHT.cpp ├── Data structures ├── BIT.cpp ├── disjointSet.cpp ├── MergeSortTree.cpp ├── ColorUpdate.cpp ├── SegmentTree.cpp ├── Tetrix.cpp ├── Sparse2D.cpp ├── treap.cpp └── AVL-tree.cpp ├── string ├── PalindromeTree.cpp ├── aho-corasick.cpp ├── rabinKarp.cpp └── suffixArray.cpp ├── non-deterministic ├── simulatedAnnealing.cpp └── HASHCODE_2022 │ ├── one_pizza.cpp │ ├── Mentorship_and_Teamwork.cpp │ └── a.cpp ├── Graph ├── LCA.cpp ├── Dinic_v3.cpp ├── HLD.cpp └── dinic_grid.cpp ├── geometry ├── closestPair.cpp ├── unionRec.cpp ├── circles_formula_quase.cpp └── circle.cpp ├── NT └── MillerRabin.cpp └── complete search └── a.cpp /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms 2 | Códigos em C++ para programação competitiva. 3 | -------------------------------------------------------------------------------- /DP /kadane.cpp: -------------------------------------------------------------------------------- 1 | vector lista; 2 | 3 | int kadane(){ 4 | 5 | int max_aqui = 0; 6 | int max_total = 0; 7 | 8 | for(int i=0;i 2 | using namespace std; 3 | const int N = 100005; 4 | int tree[N]; 5 | 6 | int query(int x){ 7 | 8 | int s = 0; 9 | 10 | while(x > 0){ 11 | s += tree[x]; 12 | x -= (x & -x); 13 | } 14 | 15 | return s; 16 | } 17 | 18 | void update(int x,int v){ 19 | 20 | while(x < N){ 21 | tree[x] += v; 22 | x += (x & -x); 23 | } 24 | } -------------------------------------------------------------------------------- /Data structures/disjointSet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | typedef vector vi; 4 | 5 | class DSU{ 6 | 7 | private: vi p,rank; 8 | public: 9 | void create(int N){ 10 | rank.assign(N,1); 11 | p.resize(N); 12 | for(int i=0;i rank[v]) swap(u,v); 26 | p[u] = v; 27 | rank[v]+= rank[u]; 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /Data structures/MergeSortTree.cpp: -------------------------------------------------------------------------------- 1 | class MergeSortTree{ 2 | struct Node{ 3 | vector vs; 4 | 5 | void add(int v){ 6 | this->vs.push_back(v); 7 | } 8 | 9 | void build(){ 10 | sort(vs.begin(), vs.end()); 11 | } 12 | }; 13 | vector nodes; 14 | 15 | int N; 16 | 17 | void add(int p, int l, int r, int x, int v){ 18 | int m = (l+r)/2; 19 | int pl = p*2; 20 | int pr = p*2 + 1; 21 | 22 | nodes[p].add(v); 23 | if(l == r) return; 24 | 25 | if(x <= m) add(pl, l, m, x, v); 26 | else add(pr, m+1, r, x, v); 27 | } 28 | 29 | void build(int p){ 30 | if(p >= nodes.size()) return; 31 | nodes[p].build(); 32 | build(2*p); 33 | build(2*p + 1); 34 | } 35 | 36 | public: 37 | MergeSortTree(int n){ 38 | N = n; 39 | nodes.resize(4*n); 40 | } 41 | 42 | void add(int x, int v){ 43 | add(1, 0, N-1, x, v); 44 | } 45 | 46 | void build(){ 47 | build(1); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /string/PalindromeTree.cpp: -------------------------------------------------------------------------------- 1 | struct eertree { 2 | vector> t; 3 | int n, last, sz; 4 | vector s, len, link; 5 | vector qt; 6 | const int SIGMA = 26; 7 | 8 | eertree(int N) { 9 | t.resize(N+2, vector(SIGMA)); 10 | s = len = link = vector(N+2); 11 | qt = vector(N+2); 12 | s[0] = -1; 13 | link[0] = 1, len[0] = 0, link[1] = 1, len[1] = -1; 14 | sz = 2, last = 0, n = 1; 15 | } 16 | 17 | void add(char c) { 18 | s[n++] = c -= 'a'; 19 | while (s[n-len[last]-2] != c) last = link[last]; 20 | if (!t[last][c]) { 21 | int prev = link[last]; 22 | while (s[n-len[prev]-2] != c) prev = link[prev]; 23 | link[sz] = t[prev][c]; 24 | len[sz] = len[last]+2; 25 | t[last][c] = sz++; 26 | } 27 | qt[last = t[last][c]]++; 28 | } 29 | int size() { return sz-2; } 30 | ll propagate() { 31 | ll ret = 0; 32 | for (int i = n; i > 1; i--) { 33 | qt[link[i]] += qt[i]; 34 | ret += qt[i]; 35 | } 36 | return ret; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /non-deterministic/simulatedAnnealing.cpp: -------------------------------------------------------------------------------- 1 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 2 | 3 | void sAnnealing(){ 4 | // pseudo-code 5 | /************* setar isso aqui inicialmente 6 | 7 | S0 = estado inicial 8 | M = numero maximo de iteracoes 9 | P = pertubacoes por iteracao 10 | L = numero maximo de sucessos por iteracoes 11 | alpha = fator de reducao da temperatura 12 | 13 | ******************************************/ 14 | 15 | auto S = S0; 16 | double T0 = tempInicial(); 17 | double T = T0; 18 | 19 | int nSucesso = 1; 20 | 21 | for(int i=0;i<=M && nSucesso > 0;i++){ 22 | nSucesso = 0; 23 | 24 | for(int j=0;j<=P && nSucesso<=L;j++){ 25 | auto Si = getneighborhood(S); 26 | double delta = score(Si) - score(S); 27 | 28 | // energia negativa -> melhor solucao 29 | if(delta <= 0.0 || exp(-delta/T) > uniform_real_distribution(0, 1.0)(rng)){ 30 | S = Si; 31 | nSucesso++; 32 | } 33 | } 34 | T = T*alpha; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /DP /Subset over Sum (sos Dp)/CF112E.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define asp "" 4 | #define aps '' 5 | #define one 1 6 | #define two 2 7 | #define dif != 8 | const int maxn = (one<<22); 9 | typedef long long ll; 10 | vector dp(maxn); 11 | vector g; 12 | 13 | void sosdp(){ 14 | 15 | int bmask; 16 | 17 | for(int i=0;i<22;i++){ 18 | for(int mask=0;mask> n; 35 | g.clear(); 36 | //for(int i=0;i> a; 40 | g.push_back(a); 41 | dp[a] = a; 42 | } 43 | 44 | ll total = 0; 45 | 46 | sosdp(); 47 | 48 | for(int i=0;i 2 | using namespace std; 3 | #define asp "" 4 | #define aps '' 5 | #define one 1 6 | #define two 2 7 | #define dif != 8 | const int maxn = (one<<20); 9 | typedef long long ll; 10 | vector dp(maxn); 11 | vector g; 12 | 13 | void sosdp(){ 14 | 15 | int bmask; 16 | 17 | for(int i=0;i<20;i++){ 18 | for(int mask=0;mask> t; 34 | while(t--){ 35 | int n; 36 | cin >> n; 37 | g.clear(); 38 | for(int i=0;i> a; 42 | g.push_back(a); 43 | dp[a]++; 44 | } 45 | 46 | ll total = 0; 47 | 48 | sosdp(); 49 | 50 | for(int i=0;i 2 | using namespace std; 3 | #define asp "" 4 | #define aps '' 5 | #define one 1 6 | #define two 2 7 | #define dif != 8 | const int maxn = (one<<24); 9 | vector dp(maxn); 10 | 11 | 12 | void sosdp(){ 13 | 14 | int bmask = 0; 15 | for(int i=0;i<24;i++){ 16 | for(int mask=0;mask> n; 45 | string s; 46 | int x; 47 | int bmask = 0; 48 | for(int i=0;i> s; 50 | bmask = 0; 51 | for(int j=0;j<3;j++){ 52 | x = s[j] - 'a'; 53 | bmask = bmask|(one< 2 | using namespace std; 3 | #define MAXN 100005 4 | #define MAXL 30 5 | 6 | int parent[MAXN][MAXL]; // MAXL = log(N) + k 7 | int level[MAXN]; 8 | vector> g; 9 | 10 | void dfs(int u){ 11 | 12 | for(auto &v: g[u]){ 13 | if(level[v] == -1){ 14 | level[v] = level[u] + 1; 15 | parent[v][0] = u; 16 | dfs(v); 17 | } 18 | } 19 | } 20 | 21 | void init(int root,int n){ 22 | 23 | for(int i=0;i=0;i--){ 43 | if(level[u] - (1<= level[v]){ 44 | u = parent[u][i]; 45 | } 46 | } 47 | 48 | if(u == v) return u; 49 | 50 | for(int i=MAXL-1;i>=0;i--){ 51 | if(parent[u][i] != -1 && parent[u][i] != parent[v][i]){ 52 | u = parent[u][i]; 53 | v = parent[v][i]; 54 | } 55 | } 56 | 57 | return parent[u][0]; 58 | } -------------------------------------------------------------------------------- /string/aho-corasick.cpp: -------------------------------------------------------------------------------- 1 | class Aho{ 2 | vector> to; 3 | vector link, term, exit, sobe; 4 | int idx = 0; 5 | 6 | public: 7 | Aho(int maxn){ 8 | to.resize(maxn); 9 | link.resize(maxn, 0); 10 | term.resize(maxn, 0); 11 | exit.resize(maxn, 0); 12 | sobe.resize(maxn, 0); 13 | } 14 | 15 | void insert(string &s){ 16 | int at = 0; 17 | for(char c: s){ 18 | auto it = to[at].find(c); 19 | if(it == to[at].end()) to[at][c] = ++idx; 20 | it = to[at].find(c); 21 | at = it->second; 22 | } 23 | term[at]++, sobe[at]++; 24 | } 25 | 26 | // nao esquecer de chamar o build dps de inserir 27 | void build(){ 28 | queue q; 29 | q.push(0); 30 | link[0] = exit[0] = -1; 31 | while(q.size()){ 32 | int i = q.front(); q.pop(); 33 | for(auto p: to[i]){ 34 | int c = p.first, j = p.second; 35 | int l = link[i]; 36 | while(l != -1 and !to[l].count(c)) l = link[l]; 37 | link[j] = l == -1 ? 0 : to[l][c]; 38 | exit[j] = term[link[j]] ? link[j] : exit[link[j]]; 39 | if(exit[j]+1) sobe[j] += sobe[exit[j]]; 40 | q.push(j); 41 | } 42 | } 43 | } 44 | 45 | // pegando todos os padroes 46 | int query(string &s){ 47 | int at=0, ans=0; 48 | for(char c: s){ 49 | while(at != -1 and !to[at].count(c)) at = link[at]; 50 | at = at == -1 ? 0 : to[at][c]; 51 | ans += sobe[at]; 52 | } 53 | 54 | return ans; 55 | } 56 | }; 57 | 58 | // link de referencia @brunomaletta: https://github.com/brunomaletta/Biblioteca/tree/master/Codigo 59 | -------------------------------------------------------------------------------- /string/rabinKarp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | typedef long long ll; 5 | 6 | #define K 256 // todos os caracteres possiveis 7 | const ll Q = 1e9 + 7; // mod 8 | 9 | string subs; 10 | string text; 11 | 12 | int search(){ 13 | 14 | int M = subs.size(); 15 | int N = text.size(); 16 | 17 | ll f = 0; 18 | ll t = 0; 19 | ll h = 1; 20 | 21 | for(int i=0;i> text; 65 | cin >> subs; 66 | 67 | ret = search(); 68 | 69 | if(ret == -1) cout << "substring nao existe na string" << endl; 70 | else cout << "substring encontrada na posicao " << ret << endl; 71 | } 72 | -------------------------------------------------------------------------------- /geometry/closestPair.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define PREC 0.00001 4 | 5 | typedef long double ld; 6 | typedef pair lld; 7 | 8 | vector Point; 9 | 10 | ld module(lld A, lld B){ 11 | 12 | ld ans,x,y; 13 | 14 | x = (B.first - A.first); 15 | y = (B.second - A.second); 16 | x *= x; 17 | y *= y; 18 | 19 | ans = sqrt(x + y); 20 | 21 | return ans; 22 | } 23 | 24 | lld inverso(lld A){ 25 | 26 | swap(A.first,A.second); 27 | 28 | return A; 29 | } 30 | 31 | ld closestPair(){ 32 | 33 | // recebe valores passados pelo vetor global (Point) 34 | 35 | set open; 36 | set::iterator itB,itE,it; 37 | 38 | // answer 39 | ld dist; 40 | // pointer 41 | int cont = 0; 42 | 43 | dist = module(Point[0],Point[1]); 44 | // salvar no set em relacao a coordenada Y 45 | lld aux; 46 | 47 | aux = inverso(Point[0]); // inverte coordenada x/y 48 | open.insert(aux); 49 | aux = inverso(Point[1]); 50 | open.insert(aux); 51 | 52 | for(int i=2;i 2 | using namespace std; 3 | #define asp "" 4 | #define aps '' 5 | #define one 1 6 | #define two 2 7 | #define dif != 8 | using namespace std; 9 | const int maxn = 10004; 10 | struct Node{ 11 | 12 | int cover = 0; 13 | int score = 0; 14 | }; 15 | 16 | vector tree(4*maxn); 17 | 18 | // build o*(n*log n) 19 | void build(int pos,int i,int j){ 20 | 21 | int esq = two*pos; 22 | int dir = two*pos + one; 23 | int mid = (i+j)/two; 24 | 25 | tree[pos].cover = 0; 26 | tree[pos].score = 0; 27 | 28 | if(i == j) return ; 29 | build(esq,i,mid); 30 | build(dir,mid+one,j); 31 | } 32 | 33 | int update(int pos,int i,int j,int l,int r,int op){ 34 | 35 | int esq = two*pos; 36 | int dir = two*pos + one; 37 | int mid = (i+j)/two; 38 | int score = 0; 39 | 40 | if(i > r || j < l) return tree[pos].score; 41 | else if(i >= l && j <= r){ 42 | 43 | tree[pos].cover += op; 44 | if(tree[pos].cover == 0 && i dif j){ 45 | tree[pos].score = tree[esq].score + tree[dir].score; 46 | } 47 | else if(tree[pos].cover == 0){ 48 | tree[pos].score = 0; 49 | } 50 | else tree[pos].score = (j-i +one); 51 | } 52 | else{ 53 | tree[pos].score = update(esq,i,mid,l,r,op); 54 | tree[pos].score += update(dir,mid+one,j,l,r,op); 55 | 56 | if(tree[pos].cover > 0) tree[pos].score = (j-i + one); 57 | } 58 | 59 | return tree[pos].score; 60 | } 61 | 62 | int main(){ 63 | 64 | int q; 65 | cin >> q; 66 | build(one,0,9); 67 | q *= two; 68 | while(q--){ 69 | int x,y; 70 | string mod; 71 | cin >> x >> y >> mod; 72 | if(mod == "add"){ 73 | cout << update(one,0,9,x,y,one) << endl; 74 | } 75 | else{ 76 | cout << update(one,0,9,x,y,-one) << endl; 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /Data structures/ColorUpdate.cpp: -------------------------------------------------------------------------------- 1 | class ColorUpdate{ 2 | 3 | public: 4 | struct Range{ 5 | 6 | Range(int l, int r, int c){ 7 | this->l = l; 8 | this->r = r; 9 | this->color = c; 10 | } 11 | 12 | Range(int l){ 13 | this->l = l; 14 | } 15 | 16 | int l; 17 | int r; 18 | int color; 19 | 20 | bool operator < (const Range &b) const { return l < b.l; } 21 | }; 22 | 23 | bool exists(int x){ 24 | 25 | auto it = ranges.upper_bound(Range(x)); 26 | 27 | if(it == ranges.begin()) return false; 28 | it--; 29 | 30 | return it->l <= x && x <= it->r; 31 | } 32 | 33 | Range get(int x){ 34 | 35 | auto it = ranges.upper_bound(Range(x)); 36 | 37 | it--; // assuming it always exists 38 | 39 | return *it; 40 | } 41 | 42 | vector erase(int l, int r){ 43 | 44 | vector ret; 45 | 46 | auto it = ranges.upper_bound(Range(l)); 47 | 48 | if(it != ranges.begin()) it--; 49 | 50 | while(it != ranges.end()){ 51 | 52 | if(it->l > r) break; 53 | else if(it->r >= l) ret.push_back(*it); 54 | 55 | it++; 56 | } 57 | 58 | if(ret.size() > 0){ 59 | 60 | int sz = ret.size(); 61 | 62 | auto s = ranges.lower_bound(Range(ret[0].l)); 63 | auto e = ranges.lower_bound(Range(ret[sz-1].l)); 64 | 65 | Range ts = *s; 66 | Range te = *e; 67 | 68 | e++; 69 | ranges.erase(s, e); 70 | 71 | Range r1 = Range(ts.l, l-1, ts.color); 72 | Range r2 = Range(r + 1, te.r, te.color); 73 | 74 | ret[0].l = max(ret[0].l, l); 75 | ret[sz-1].r = min(ret[sz-1].r, r); 76 | 77 | if(r1.l <= r1.r) ranges.insert(r1); 78 | if(r2.l <= r2.r) ranges.insert(r2); 79 | } 80 | 81 | return ret; 82 | } 83 | 84 | vector upd(int l, int r, int color){ 85 | 86 | vector ret = erase(l, r); 87 | 88 | ranges.insert(Range(l, r, color)); 89 | 90 | return ret; 91 | } 92 | 93 | private: 94 | set ranges; 95 | }; 96 | -------------------------------------------------------------------------------- /Data structures/SegmentTree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | add: add a value to current node on tree 3 | join: join a query on lazy node 4 | merge: combine two nodes into one */ 5 | class SegTree{ 6 | int N; 7 | vector tree; 8 | vector lazy; 9 | 10 | ll add(ll curr, int i, int j, ll v){ 11 | return curr + v * ll(j - i + 1); 12 | } 13 | 14 | ll join(ll curr, ll v){ 15 | return curr + v; 16 | } 17 | 18 | ll merge(ll v1, ll v2){ 19 | return v1 + v2; 20 | } 21 | 22 | void propagate(int pos, int i, int j){ 23 | int esq = 2*pos; 24 | int dir = 2*pos + 1; 25 | 26 | if(lazy[pos]){ 27 | tree[pos] = add(tree[pos], i, j, lazy[pos]); 28 | if(i < j){ 29 | lazy[esq] = join(lazy[esq], lazy[pos]); 30 | lazy[dir] = join(lazy[dir], lazy[pos]); 31 | } 32 | lazy[pos] = 0; 33 | } 34 | } 35 | 36 | void upd(int pos, int i, int j, int l, int r, ll v){ 37 | int esq = 2*pos; 38 | int dir = 2*pos + 1; 39 | int mid = (i+j)/2; 40 | 41 | propagate(pos, i, j); 42 | 43 | if(i > r || j < l) return; 44 | else if(i >= l && j <= r){ 45 | tree[pos] = add(tree[pos], i, j, v); 46 | if(i < j){ 47 | lazy[esq] = join(lazy[esq], v); 48 | lazy[dir] = join(lazy[dir], v); 49 | } 50 | } 51 | else{ 52 | upd(esq, i, mid, l, r, v); 53 | upd(dir, mid+1, j, l, r, v); 54 | tree[pos] = merge(tree[esq], tree[dir]); 55 | } 56 | } 57 | 58 | ll qry(int pos, int i, int j, int l, int r){ 59 | int esq = 2*pos; 60 | int dir = 2*pos + 1; 61 | int mid = (i+j)/2; 62 | 63 | propagate(pos, i, j); 64 | 65 | if(i > r || j < l) return 0; 66 | if(i >= l && j <= r) return tree[pos]; 67 | else return merge(qry(esq, i, mid, l, r), qry(dir, mid+1, j, l, r)); 68 | } 69 | 70 | public: 71 | SegTree(int n){ 72 | N = n; 73 | tree.resize(4*N + 3); 74 | lazy.resize(4*N + 3); 75 | } 76 | 77 | void upd(int l, int r, ll v){ 78 | upd(1, 0, N-1, l, r, v); 79 | } 80 | 81 | ll qry(int l, int r){ 82 | return qry(1, 0, N-1, l, r); 83 | } 84 | }; 85 | -------------------------------------------------------------------------------- /Graph/Dinic_v3.cpp: -------------------------------------------------------------------------------- 1 | const ll INF = 1e9 + 7; 2 | 3 | class Dinic{ 4 | int N; 5 | vector level; 6 | vector dead; 7 | 8 | public: 9 | struct Edge{ 10 | Edge(int a,ll x){ 11 | v = a; 12 | cap = x; 13 | } 14 | int v; 15 | ll cap; 16 | }; 17 | int source; 18 | int sink; 19 | vector edge; 20 | vector> g; 21 | 22 | Dinic(int n){ 23 | g.resize(n); 24 | N = n; 25 | level.resize(n); 26 | } 27 | 28 | void setInit(int u,int v){ 29 | source = u; 30 | sink = v; 31 | } 32 | 33 | void addEdge(int u,int v,ll cap){ 34 | g[u].push_back(edge.size()); 35 | edge.push_back(Edge(v,cap)); 36 | g[v].push_back(edge.size()); 37 | edge.push_back(Edge(u,0)); 38 | } 39 | private: 40 | 41 | bool BFS(){ 42 | 43 | for(int i=0;i q; 48 | q.push(source); 49 | 50 | while(!q.empty()){ 51 | 52 | int u = q.front(); 53 | q.pop(); 54 | 55 | if(u == sink) return true; 56 | 57 | for(auto x: g[u]){ 58 | if(level[edge[x].v] == INF && edge[x].cap > 0){ 59 | level[edge[x].v] = level[u] + 1; 60 | q.push(edge[x].v); 61 | } 62 | } 63 | } 64 | return false; 65 | } 66 | 67 | ll maxflow(int u,ll flow){ 68 | 69 | if(dead[u]) return 0; 70 | 71 | ll ret = 0; 72 | ll f = 0; 73 | if(flow == 0) return 0; 74 | if(u == sink) return flow; 75 | 76 | for(auto i: g[u]){ 77 | if(level[edge[i].v] != level[u] + 1) continue; 78 | f = maxflow(edge[i].v,min(edge[i].cap,flow)); 79 | int x = (i%2 == 0?i+1:i-1); 80 | flow -= f; 81 | ret += f; 82 | edge[i].cap -= f; 83 | edge[x].cap += f; 84 | } 85 | 86 | if(ret == 0) dead[u] = true; 87 | 88 | return ret; 89 | } 90 | public: 91 | ll run(){ 92 | 93 | ll flow = 0; 94 | while(BFS()){ 95 | flow += maxflow(source,INF); 96 | } 97 | 98 | return flow; 99 | } 100 | }; 101 | -------------------------------------------------------------------------------- /DP /CHTPersistent.cpp: -------------------------------------------------------------------------------- 1 | class CHTPersistent{ 2 | struct Line{ 3 | ll m; 4 | ll c; 5 | Line(){} 6 | Line(ll _m, ll _c): m(_m), c(_c){} 7 | }; 8 | 9 | vector> hull; 10 | int SZ = 0; 11 | vector version_idx; 12 | vector version_sz; 13 | 14 | double inter(Line t1, Line t2){ 15 | double ret; 16 | ret = (double)(t2.c - t1.c)/(t1.m - t2.m); 17 | return ret; 18 | } 19 | 20 | void add(Line curr){ 21 | Line temp, temp2; 22 | version_sz.push_back(SZ); 23 | 24 | if(SZ > 1){ 25 | int s = 0; 26 | int e = SZ-1; 27 | 28 | while(s < e){ 29 | int p = (s+e)/2; 30 | 31 | temp = hull[p+1].back(); 32 | temp2 = hull[p].back(); 33 | 34 | double point = inter(temp, temp2); 35 | double point2 = inter(temp, curr); 36 | 37 | if(point < point2){ 38 | s = p+1; 39 | } 40 | else{ 41 | e = p; 42 | } 43 | } 44 | SZ = s+1; 45 | } 46 | 47 | if(hull.size() == SZ){ 48 | vector x; 49 | hull.push_back(x); 50 | } 51 | 52 | hull[SZ].push_back(curr); 53 | version_idx.push_back(SZ); 54 | SZ++; 55 | } 56 | 57 | public: 58 | void add(ll m, ll c){ 59 | add(Line(m, c)); 60 | } 61 | 62 | ll query(ll find){ 63 | int s = 0; 64 | int e = SZ-1; 65 | 66 | while(s < e){ 67 | int p = (s+e)/2; 68 | 69 | double point = inter(hull[p].back(), hull[p+1].back()); 70 | if(point < find){ 71 | s = p+1; 72 | } 73 | else{ 74 | e = p; 75 | } 76 | } 77 | 78 | ll ret = (hull[s].back().m * find) + hull[s].back().c; 79 | return ret; 80 | } 81 | 82 | void rollback(){ 83 | SZ = version_sz.back(); 84 | version_sz.pop_back(); 85 | hull[version_idx.back()].pop_back(); 86 | version_idx.pop_back(); 87 | } 88 | 89 | int size(){ 90 | return SZ; 91 | } 92 | }; 93 | 94 | // log(n) for query & add. O(1) for rollback. All lines should be added in crescent angular coef order 95 | -------------------------------------------------------------------------------- /NT/MillerRabin.cpp: -------------------------------------------------------------------------------- 1 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 2 | ll rnd(ll a, ll b){ 3 | return uniform_int_distribution(a, b)(rng); 4 | } 5 | 6 | //Retorna a*b % mod. é necessário pra multiplicar 7 | //dois long long sem dar overflow. 8 | //Se os números que vc quer testar são menores que 2*10^9, 9 | //pode deixar o return (a*b)%mod. 10 | ll mod_mul(ll a, ll b, ll mod){ 11 | //return (a*b)%mod; 12 | ll cur_mod = a; 13 | ll ans = 0; 14 | for (int i=0; i<63; i++){ 15 | if ((b>>i)&1) ans = (ans + cur_mod)%mod; 16 | cur_mod = (2*cur_mod) % mod; 17 | } 18 | return ans; 19 | } 20 | 21 | //Exponenciação rápida - calcula (a^e)%mod em O(log(e)). 22 | ll fexp(ll a, ll e, ll mod){ 23 | if (e == 0) return 1; 24 | ll p = fexp(a, e/2, mod); 25 | p = mod_mul(p, p, mod); 26 | if (e%2 == 1) 27 | p = mod_mul(p, a, mod); 28 | return p; 29 | } 30 | 31 | //Miller-Rabin. Checa se o número p é fortemente pseudoprimo na base a. 32 | //Complexidade: O(log(p)) sem modmul, O(log²(p)) com modmul. 33 | bool miller_rabin (ll p, ll a){ 34 | 35 | ll q = p-1, k=0; 36 | while(q % 2 == 0){ 37 | q /= 2; 38 | k++; 39 | } 40 | 41 | ll cur = fexp(a, q, p); 42 | if (cur == 1 or cur == p-1) return true; 43 | 44 | for (int i=0; i número testado, k => número de bases. 55 | //A probabilidade de erro (identificar que um 56 | //número é primo quando na vdd é composto) é de (1/4)^k 57 | //k = 40 é uma boa opção, se o TL apertar vc pode diminuir isso aí 58 | bool is_probably_prime(ll p, int k){ 59 | if (p == 0 or p == 1) return false; 60 | if (p == 2 or p == 3) return true; 61 | if (p%2 == 0) return false; 62 | 63 | for (int i=0; i 10 | using namespace std; 11 | 12 | typedef struct{ 13 | 14 | int m; // inclinacao 15 | int c; // constante da funcao 16 | 17 | }line; 18 | 19 | deque dq; // deque para adicionar linhas 20 | 21 | // recebe duas linhas e calcula seu ponto de interseccao no eixo x. NAo podem ter inclinacoes iguais 22 | double inter(line t1,line t2){ 23 | 24 | double ret; 25 | 26 | ret = (double) (t2.c - t1.c)/(t1.m - t2.m); 27 | 28 | return ret; 29 | } 30 | 31 | // funcao para adicionar uma nova linha 32 | 33 | void add(line novo){ 34 | 35 | // criando o convex hull (para cascos inferiores) 36 | bool ok = true; 37 | line temp,temp2; 38 | double point,point2; 39 | 40 | while(dq.size() > 1 && ok){ 41 | temp = dq.back(); 42 | dq.pop_back(); // remove temporariamente a ultima linha 43 | temp2 = dq.back(); 44 | point = inter(temp,temp2); // calcula a interseccao das retas e devolve a coordenada x 45 | point2 = inter(temp,novo); // ponto de interseccao da ultima reta e da reta que desejo adicionar 46 | 47 | // caso point < point2, entao a reta removida nao pode ser removida. Logo, readicionamos a reta 48 | if(point < point2){ 49 | dq.push_back(temp); // devolvendo a reta removida 50 | ok = false; // condicao para parar o loop 51 | } 52 | } 53 | // apos sair do while, adicionamos nossa nova reta no seu devido lugar 54 | dq.push_back(novo); 55 | } 56 | 57 | // funcao para consultar 58 | int query(int find){ 59 | 60 | int s,e,p; 61 | double point; 62 | int ret; 63 | s = 0; 64 | e = dq.size() - 1; 65 | p = (s+e)/2; 66 | 67 | while(s < e){ 68 | 69 | point = inter(dq[p],dq[p+1]); 70 | if(point < find){ 71 | s = p+1; 72 | p = (s+e)/2; 73 | } 74 | else{ 75 | e = p; 76 | p = (s+e)/2; 77 | } 78 | } 79 | ret = (dq[p].m * find) + dq[p].c; 80 | 81 | return ret; 82 | 83 | } 84 | 85 | int main(){ 86 | 87 | 88 | int p,c; 89 | line aux; 90 | 91 | for(int i=0;i<4;i++){ 92 | scanf("%d %d",&p,&c); 93 | aux.m = p; 94 | aux.c = c; 95 | add(aux); 96 | printf("Minha deque contem:\n"); 97 | for(int j=0;j ii; 2 | 3 | class SA{ 4 | 5 | public: 6 | vector idx; 7 | vector lcp; 8 | vector rank; 9 | string word; 10 | 11 | void process(string &text){ 12 | 13 | text += '$'; 14 | word = text; 15 | int n = text.size(); 16 | rank.resize(n); 17 | 18 | vector lista; 19 | for(int i=0;i aux(n); 37 | vector count(n,0); 38 | 39 | for(int i=0;i=0;i--){ 44 | int x = (idx[i]-k+n)%n; 45 | aux[count[rank[x]] - 1] = x; 46 | count[rank[x]]--; 47 | } 48 | swap(idx,aux); 49 | 50 | vector novo(n); 51 | 52 | novo[idx[0]] = 0; 53 | classe = 0; 54 | for(int i=1;i= pat[i]){ 102 | e = p; 103 | } 104 | else{ 105 | s = p+1; 106 | } 107 | } 108 | dl = s; 109 | e = dr; 110 | while(s < e){ 111 | int p = (s+e)/2; 112 | 113 | int x = idx[p] + i; 114 | if(word[x] > pat[i]){ 115 | e = p; 116 | } 117 | else{ 118 | s = p+1; 119 | } 120 | } 121 | if(word[idx[s]+i] > pat[i]) s--; 122 | dr = s; 123 | } 124 | 125 | return dl <= dr; 126 | } 127 | }; 128 | -------------------------------------------------------------------------------- /Data structures/Tetrix.cpp: -------------------------------------------------------------------------------- 1 | class Tetrix{ 2 | private: 3 | 4 | struct Range{ 5 | int l, r; 6 | int id; 7 | bool active; 8 | 9 | Range(int l, int r, int id): l(l), r(r), id(id), active(true) {} 10 | }; 11 | 12 | int MAXN; 13 | vector> st; 14 | vector ranges; 15 | vector tree; 16 | 17 | bool isCovered(int i, int j, int l, int r){ 18 | return (l <= i && r >= j); 19 | } 20 | 21 | bool isDisjoint(int i, int j, int l, int r){ 22 | return (l > j || r < i); 23 | } 24 | 25 | int lazyTop(int pos){ 26 | return (st[pos].empty()? -1 : st[pos].top()); 27 | } 28 | 29 | void lazy(int pos){ 30 | while(!st[pos].empty()){ 31 | int id = st[pos].top(); 32 | if(!ranges[id].active) st[pos].pop(); 33 | else break; 34 | } 35 | } 36 | 37 | int add(int pos, int i, int j, Range &range){ 38 | int esq = 2*pos; 39 | int dir = 2*pos + 1; 40 | int mid = (i+j)/2; 41 | 42 | lazy(pos); 43 | 44 | if(isDisjoint(i, j, range.l, range.r)); 45 | else if(isCovered(i, j, range.l, range.r)){ 46 | st[pos].push(range.id); 47 | } 48 | else{ 49 | tree[pos] = max(add(esq, i, mid, range), add(dir, mid+1, j, range)); 50 | } 51 | 52 | return max(tree[pos], lazyTop(pos)); 53 | } 54 | 55 | int remove(int pos, int i, int j, Range &range){ 56 | int esq = 2*pos; 57 | int dir = 2*pos + 1; 58 | int mid = (i+j)/2; 59 | 60 | lazy(pos); 61 | 62 | if(isDisjoint(i, j, range.l, range.r) || isCovered(i, j, range.l, range.r)); 63 | else{ 64 | tree[pos] = max(remove(esq, i, mid, range), remove(dir, mid+1, j, range)); 65 | } 66 | 67 | return max(tree[pos], lazyTop(pos)); 68 | } 69 | 70 | int query(int pos, int i, int j, int l, int r){ 71 | int esq = 2*pos; 72 | int dir = 2*pos + 1; 73 | int mid = (i+j)/2; 74 | 75 | if(isDisjoint(i, j, l, r)) return -1; 76 | else if(isCovered(i, j, l, r)) return max(tree[pos], lazyTop(pos)); 77 | else{ 78 | return max({query(esq, i, mid, l, r), query(dir, mid+1, j, l, r), lazyTop(pos)}); 79 | } 80 | } 81 | 82 | public: 83 | 84 | Tetrix(int maxn){ 85 | MAXN = maxn; 86 | tree.resize(4*MAXN + 3, -1); 87 | st.resize(4*MAXN + 3); 88 | } 89 | 90 | void push(int l, int r, int id){ 91 | Range range(l, r, id); 92 | ranges.push_back(range); 93 | add(1, 0, MAXN-1, range); 94 | } 95 | 96 | void pop(int id){ 97 | Range range = ranges[id]; 98 | ranges[id].active = false; 99 | remove(1, 0, MAXN-1, range); 100 | } 101 | 102 | int get(int l, int r){ 103 | int id = query(1, 0, MAXN-1, l, r); 104 | return id; 105 | } 106 | }; 107 | -------------------------------------------------------------------------------- /complete search/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | typedef pair ii; 5 | typedef vector vi; 6 | vector> g; 7 | vector> grid; 8 | 9 | void seta(vi &att){ 10 | 11 | for(int i=0;i all; 66 | for(int j=0;j> n >> m; 103 | vector> mapa; 104 | preProcess(m); 105 | mapa.resize(n); 106 | for(int i=0;i> a; 110 | mapa[i].push_back(a); 111 | } 112 | } 113 | 114 | int maxi = 0; 115 | m--; 116 | for(int i=0;i 2 | 3 | using namespace std; 4 | const double PREC = 0.000001; 5 | 6 | 7 | 8 | struct Circle{ 9 | 10 | 11 | 12 | double x; 13 | 14 | double y; 15 | 16 | double r; 17 | 18 | }; 19 | 20 | 21 | 22 | struct Line{ 23 | 24 | double m; 25 | 26 | double b; 27 | 28 | }; 29 | 30 | 31 | 32 | vector> LineCircle(Line L,Circle C){ 33 | 34 | 35 | 36 | vector> lista; 37 | 38 | 39 | 40 | double a = L.m*L.m + 1.0; 41 | 42 | double b = 2.0*(L.m*L.b - L.m*C.y - C.x); 43 | 44 | double c = (L.b*L.b - 2.0*L.b*C.y + C.y*C.y + C.x*C.x - C.r*C.r); 45 | 46 | 47 | 48 | double delta = b*b - 4.0*a*c; 49 | 50 | if(delta < 0.0) return lista; // nao ha interseccao; 51 | 52 | 53 | 54 | double x = (-b + sqrt(delta))/(2.0*a); 55 | 56 | double y = L.m * x + L.b; 57 | 58 | lista.push_back(make_pair(x,y)); 59 | 60 | x = (-b - sqrt(delta))/(2.0*a); 61 | 62 | y = L.m * x + L.b; 63 | 64 | lista.push_back(make_pair(x,y)); 65 | 66 | 67 | 68 | return lista; 69 | 70 | } 71 | 72 | 73 | 74 | vector> intersect(Circle A, Circle B){ 75 | 76 | 77 | 78 | vector> lista; 79 | 80 | 81 | 82 | B.x -= A.x; 83 | 84 | B.y -= A.y; 85 | 86 | 87 | 88 | double dist = sqrt(B.x*B.x + B.y*B.y); 89 | 90 | if(A.r + B.r < dist) return lista; // nao ha interseccao 91 | 92 | 93 | 94 | double resto = dist - B.r; 95 | 96 | resto += (A.r - resto)*(A.r)/(A.r+B.r); 97 | 98 | 99 | 100 | double x = resto*B.x/dist; 101 | 102 | double y = resto*B.y/dist; 103 | 104 | double m; 105 | 106 | double dx = B.y - y + x; 107 | double dy = x - B.x + y; 108 | 109 | if(abs(x - dx) < PREC) m = (y - dy)/PREC; 110 | else m = (y - dy)/(x - dx); 111 | 112 | Line aux; 113 | 114 | aux.m = m; 115 | 116 | aux.b = -m*x + y; 117 | 118 | lista = LineCircle(aux,B); 119 | 120 | 121 | 122 | for(int i=0;i> A.x >> A.y >> A.r; 148 | cin >> B.x >> B.y >> B.r; 149 | 150 | vector> ret = intersect(A,B); 151 | 152 | if(ret.size() == 0) cout << "nao existe" << endl; 153 | else{ 154 | for(int i=0;ic = c; 9 | for(int i=0;i<4;i++) this->nodes[i] = NULL; 10 | } 11 | }; 12 | 13 | vector matrix; 14 | 15 | typedef Node* node; 16 | 17 | node root = NULL; 18 | ll default_color = 0; 19 | 20 | node create(ll c){ 21 | node t = new Node(c); 22 | return t; 23 | } 24 | 25 | bool isLeaf(const vector &grid){ 26 | return grid[0] == grid[1] && grid[2] == grid[3]; 27 | } 28 | 29 | bool isInside(const vector &grid, const vector &window){ 30 | bool eq = (grid[0] >= window[0] && grid[1] <= window[1]); 31 | eq = eq & (grid[2] >= window[2] && grid[3] <= window[3]); 32 | 33 | return eq; 34 | } 35 | 36 | bool isDisjoint(const vector &grid, const vector &window){ 37 | bool eq = (grid[0] > window[1] || grid[1] < window[0]); 38 | eq = eq | (grid[2] > window[3] || grid[3] < window[2]); 39 | 40 | return eq; 41 | } 42 | 43 | void propagate(node t, const vector &grid){ 44 | if(t->c == default_color) return ; 45 | if(isLeaf(grid)) return ; 46 | 47 | for(int i=0;i<2;i++){ 48 | for(int j=0;j<2;j++){ 49 | int id = 2*i + j; 50 | 51 | if(!t->nodes[id]) t->nodes[id] = create(t->c); 52 | else (t->nodes[id])->c = t->c; 53 | 54 | if(grid[2] == grid[3]) break; 55 | } 56 | 57 | if(grid[0] == grid[1]) break; 58 | } 59 | 60 | t->c = default_color; 61 | } 62 | 63 | void replace(node &t, ll c, const vector &grid, const vector &window){ 64 | if(!t) t = create(default_color); 65 | propagate(t, grid); 66 | 67 | if(isDisjoint(grid, window)) return ; 68 | if(isInside(grid, window)){ 69 | t->c = c; 70 | return ; 71 | } 72 | 73 | ll midx = (grid[1] + grid[0])/2; 74 | ll midy = (grid[2] + grid[3])/2; 75 | 76 | for(int i=0;i<2;i++){ 77 | vector ngrid(4); 78 | 79 | if(i == 0){ 80 | ngrid[0] = grid[0]; 81 | ngrid[1] = midx; 82 | } 83 | else{ 84 | ngrid[0] = midx+ 1; 85 | ngrid[1] = grid[1]; 86 | } 87 | 88 | for(int j=0;j<2;j++){ 89 | int id = i*2 + j; 90 | 91 | if(j == 0){ 92 | ngrid[2] = grid[2]; 93 | ngrid[3] = midy; 94 | } 95 | else{ 96 | ngrid[2] = midy + 1; 97 | ngrid[3] = grid[3]; 98 | } 99 | 100 | replace(t->nodes[id], c, ngrid, window); 101 | 102 | if(grid[2] == grid[3]) break; 103 | } 104 | if(grid[0] == grid[1]) break; 105 | } 106 | } 107 | 108 | void getDistinctColors(node t, set &colors){ 109 | if(!t) return ; 110 | 111 | if(t->c == default_color){ 112 | for(int i=0;i<4;i++) getDistinctColors(t->nodes[i], colors); 113 | } 114 | else colors.insert(t->c); 115 | } 116 | 117 | public: 118 | Sparse2D(ll x0, ll xf, ll y0 = 0, ll yf = 0){ 119 | matrix.resize(4); 120 | matrix[0] = x0; 121 | matrix[1] = xf; 122 | matrix[2] = y0; 123 | matrix[3] = yf; 124 | } 125 | 126 | void replace(ll c, ll x0, ll xf, ll y0 = 0, ll yf = 0){ 127 | vector window(4); 128 | window[0] = x0; 129 | window[1] = xf; 130 | window[2] = y0; 131 | window[3] = yf; 132 | 133 | replace(root, c, matrix, window); 134 | } 135 | 136 | int colorsCount(){ 137 | set colors; 138 | 139 | getDistinctColors(root, colors); 140 | 141 | return colors.size(); 142 | } 143 | }; 144 | 145 | #TODO: improve memory management 146 | -------------------------------------------------------------------------------- /Data structures/treap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | typedef long long ll; 5 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 6 | 7 | class Treap{ 8 | 9 | private: 10 | struct Node{ 11 | 12 | ll key; // key 13 | ll prior; // randomized 14 | ll value; // value for this node 15 | ll tree; // value for this subtree 16 | 17 | Node *l; // data of l node 18 | Node *r; // data of r node 19 | Node(){} 20 | Node(ll key, ll value): key(key), 21 | value(value), prior(uniform_int_distribution()(rng)), l(NULL), r(NULL){} 22 | }; 23 | typedef Node* node; 24 | 25 | node root = NULL; 26 | 27 | void split(node t, ll key, node &l, node &r){ 28 | 29 | if(!t){ 30 | l = r = NULL; 31 | } 32 | else if(t->key <= key){ 33 | split(t->r, key, t->r, r), l = t; 34 | } 35 | else{ 36 | split(t->l, key, l, t->l), r = t; 37 | } 38 | 39 | update(t); 40 | } 41 | 42 | void insert(node &t, node item){ 43 | 44 | if(!t){ 45 | t = item; 46 | } 47 | else if(item->prior > t->prior){ 48 | split(t, item->key, item->l, item->r), t = item; 49 | } 50 | else if(t->key <= item->key){ 51 | insert(t->r, item); 52 | } 53 | else{ 54 | insert(t->l, item); 55 | } 56 | 57 | update(t); 58 | } 59 | 60 | void merge(node &t, node l, node r) { 61 | if (!l || !r) 62 | t = l ? l : r; 63 | else if (l->prior > r->prior) 64 | merge (l->r, l->r, r), t = l; 65 | else 66 | merge (r->l, l, r->l), t = r; 67 | 68 | update(t); 69 | } 70 | 71 | void erase(node &t, ll key){ 72 | node th; 73 | 74 | if(!t) return ; 75 | 76 | if(t->key == key){ 77 | th = t; 78 | merge(t, t->l, t-> r); 79 | delete th; 80 | } 81 | else if(t->key < key){ 82 | erase(t->r, key); 83 | } 84 | else{ 85 | erase(t->l, key); 86 | } 87 | 88 | update(t); 89 | } 90 | 91 | ll getValue(node t){ 92 | 93 | if(!t) return -1; 94 | 95 | return t->value; 96 | } 97 | 98 | ll getTree(node t){ 99 | 100 | if(!t) return 0; 101 | 102 | return t->tree; 103 | } 104 | 105 | void update(node t){ 106 | 107 | if(!t) return ; 108 | t->tree = t->value; 109 | t->tree += getTree(t->l); 110 | t->tree += getTree(t->r); 111 | } 112 | 113 | ll prefix(node t, ll key){ 114 | 115 | if(!t) return 0; 116 | 117 | if(t->key <= key){ 118 | return getTree(t->l) + prefix(t->r, key) + t->value; 119 | } 120 | else{ 121 | return prefix(t->l, key); 122 | } 123 | } 124 | 125 | ll suffix(node t, ll key){ 126 | 127 | if(!t) return 0; 128 | 129 | if(t->key < key){ 130 | return suffix(t->r, key); 131 | } 132 | else{ 133 | return suffix(t->l, key) + getTree(t->r) + t->value; 134 | } 135 | } 136 | 137 | ll find(node t, ll key){ 138 | 139 | if(!t) return -1; 140 | 141 | if(t->key == key) return t->value; 142 | if(t->key < key) return find(t->r, key); 143 | else return find(t->l, key); 144 | } 145 | 146 | public: 147 | void add(ll key, ll value){ 148 | node t = new Node(key, value); 149 | insert(root, t); 150 | } 151 | 152 | void remove(ll key){ 153 | erase(root, key); 154 | } 155 | 156 | ll prefix(ll key){ 157 | return prefix(root, key); 158 | } 159 | 160 | ll suffix(ll key){ 161 | return suffix(root, key); 162 | } 163 | 164 | ll find(ll key){ 165 | return find(root, key); 166 | } 167 | }; 168 | 169 | int main(){ 170 | 171 | } 172 | -------------------------------------------------------------------------------- /Graph/HLD.cpp: -------------------------------------------------------------------------------- 1 | typedef long long ll; 2 | typedef pair ii; 3 | 4 | class HLD{ 5 | 6 | vector pos; 7 | vector parent; 8 | vector sz; 9 | vector level; 10 | vector head; // jaja 11 | vector> g; 12 | 13 | // segment tree 14 | vector tree; 15 | vector lazy; 16 | 17 | int N; 18 | 19 | void propagate(int pos,int i,int j){ 20 | 21 | } 22 | 23 | int query(int pos,int i,int j,int l,int r){ 24 | 25 | } 26 | 27 | void update(int pos,int i,int j,int l,int r,int w){ 28 | 29 | } 30 | 31 | void dfs(int u,int lv){ 32 | 33 | level[u] = lv; 34 | sz[u] = 1; 35 | int bigChild = 0; 36 | 37 | for(int i=0;i bigChild) swap(g[u][i],g[u][0]); 45 | bigChild = max(bigChild,sz[v]); 46 | } 47 | } 48 | 49 | void decompose(int u,int &x,bool keep){ 50 | 51 | if(keep){ 52 | head[u] = head[parent[u]]; 53 | } 54 | else head[u] = u; 55 | 56 | pos[u] = x++; 57 | 58 | if(sz[u] > 1) decompose(g[u][0].first,x,true); 59 | 60 | for(int i=1;i level[head[v]]) u = parent[head[u]]; 97 | else v = parent[head[v]]; 98 | } 99 | return (level[u] < level[v]?u:v); 100 | } 101 | 102 | int join(int a,int b){ 103 | 104 | return a+b; 105 | } 106 | 107 | int get(int u,int v){ 108 | int l = LCA(u,v); 109 | int ret = 0; 110 | int add; 111 | while(head[u] != head[l]){ 112 | add = query(1,0,N-1,pos[head[u]],pos[u]); 113 | ret = join(add,ret); 114 | u = parent[head[u]]; 115 | } 116 | add = query(1,0,N-1,pos[l]+1,pos[u]); 117 | ret = join(add,ret); 118 | while(head[v] != head[l]){ 119 | add = query(1,0,N-1,pos[head[v]],pos[v]); 120 | ret = join(add,ret); 121 | v = parent[head[v]]; 122 | } 123 | add = query(1,0,N-1,pos[l],pos[v]);// para hld de arestas, mude isso aqui para pos[l]+1 124 | ret = join(add,ret); 125 | return ret; 126 | } 127 | 128 | void flip(int u,int v,int w){ 129 | int l = LCA(u,v); 130 | while(head[u] != head[l]){ 131 | update(1,0,N-1,pos[head[u]],pos[u],w); 132 | u = parent[head[u]]; 133 | } 134 | update(1,0,N-1,pos[l]+1,pos[u],w); 135 | while(head[v] != head[l]){ 136 | update(1,0,N-1,pos[head[v]],pos[v],w); 137 | v = parent[head[v]]; 138 | } 139 | update(1,0,N-1,pos[l],pos[v],w); // para hld de arestas, mude isso aqui para pos[l]+1 140 | } 141 | 142 | int lenPath(int u,int v){ 143 | int l = LCA(u,v); 144 | int ret = level[u] - level[l]; 145 | ret += level[v] - level[l]; 146 | ret++; 147 | return ret; 148 | } 149 | }; 150 | 151 | int main(){ 152 | 153 | HLD hld(n);// 0-based 154 | 155 | for(int i=0;i> u >> v >> w; 158 | hld.addEdge(u,v,w); 159 | hld.addEdge(v,u,w); 160 | } 161 | 162 | hld.init(); 163 | 164 | 165 | hld.flip(u,v,w); 166 | 167 | for(int i=0;i 2 | using namespace std; 3 | 4 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 5 | 6 | int N; 7 | 8 | map ingr_id; 9 | vector id_ingr; 10 | 11 | vector> like; 12 | vector> dlike; 13 | 14 | vector pizza; 15 | 16 | void Rinput(){ 17 | 18 | cin >> N; 19 | 20 | for(int i=0;i> l; 23 | vector aux; 24 | for(int j=0;j> x; 27 | if(ingr_id.count(x) == 0){ 28 | ingr_id[x] = id_ingr.size(); 29 | id_ingr.push_back(x); 30 | } 31 | 32 | int id = ingr_id[x]; 33 | aux.push_back(id); 34 | } 35 | 36 | like.push_back(aux); 37 | 38 | int d; 39 | cin >> d; 40 | aux.clear(); 41 | for(int j=0;j> x; 44 | if(ingr_id.count(x) == 0){ 45 | ingr_id[x] = id_ingr.size(); 46 | id_ingr.push_back(x); 47 | } 48 | 49 | int id = ingr_id[x]; 50 | aux.push_back(id); 51 | } 52 | 53 | dlike.push_back(aux); 54 | } 55 | 56 | pizza.resize(id_ingr.size(), false); 57 | } 58 | 59 | void Woutput(int id, string name, vector &S){ 60 | int ing = 0; 61 | for(int i=0;i(0, pizza.size())(rng); 82 | return id; 83 | } 84 | 85 | int score(vector &S){ 86 | 87 | int sc = 0; 88 | 89 | for(int i=0;i S = pizza; 137 | double T0 = 200; 138 | double T = T0; 139 | 140 | int nSucesso = 1; 141 | 142 | int log_size = 100; 143 | 144 | for(int i=0;i<=M && nSucesso > 0;i++){ 145 | if(i%log_size == 0){ 146 | printinfo(T, i, score(S)); 147 | //Woutput(i/log_size, test, S); 148 | } 149 | 150 | nSucesso = 0; 151 | 152 | for(int j=0;j<=P && nSucesso<=L;j++){ 153 | double score_s = score(S); 154 | int peek = getneighborhood(); 155 | 156 | S[peek] = !(S[peek]); 157 | 158 | double score_si = score(S); 159 | 160 | double delta = score_s - score_si; 161 | 162 | // energia negativa -> melhor solucao 163 | if(delta <= 0.0 || exp(-delta/T) > uniform_real_distribution(0, 1.0)(rng)){ 164 | nSucesso++; 165 | } 166 | else{ 167 | S[peek] = !(S[peek]); 168 | } 169 | } 170 | T = T*alpha; 171 | } 172 | 173 | Woutput(M/log_size, test, S); 174 | } 175 | 176 | int main(){ 177 | 178 | ios::sync_with_stdio(0); 179 | cin.tie(0); 180 | cout.tie(0); 181 | 182 | Rinput(); 183 | sAnnealing(); 184 | } 185 | -------------------------------------------------------------------------------- /Data structures/AVL-tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef struct nod{ 5 | 6 | int key; 7 | int nodecountL; 8 | int nodecountR; 9 | int height; 10 | struct nod *left; 11 | struct nod *right; 12 | }Node; 13 | 14 | typedef struct{ 15 | 16 | Node *root; 17 | }BST; 18 | 19 | BST *create_bst(){ 20 | 21 | BST *bst; 22 | 23 | bst = (BST *) malloc(sizeof(BST)); 24 | bst->root = NULL; 25 | 26 | return bst; 27 | } 28 | 29 | int max(int a,int b){ 30 | 31 | if(a>b) return a; 32 | else return b; 33 | } 34 | 35 | int height(Node *node){ 36 | 37 | if(node==NULL) return -1; 38 | else return node->height; 39 | } 40 | 41 | int total(Node *node){ 42 | 43 | if(node==NULL) return 0; 44 | else return (1+(node->nodecountL) + (node->nodecountR)); 45 | } 46 | 47 | Node *leftRotate(Node *node){ 48 | 49 | Node *r,*rl; 50 | 51 | r = node->right; 52 | rl = r->left; 53 | r->left = node; 54 | node->right = rl; 55 | node->nodecountR = total(rl); 56 | r->nodecountL = total(node); 57 | node->height = max(height(node->left),height(node->right)) + 1; 58 | r->height = max(height(r->left),height(r->right)) + 1; 59 | 60 | return r; 61 | } 62 | 63 | Node *rightRotate(Node *node){ 64 | 65 | Node *l,*lr; 66 | 67 | l = node->left; 68 | lr = l->right; 69 | l->right = node; 70 | node->left = lr; 71 | node->nodecountL = total(lr); 72 | l->nodecountR = total(node); 73 | node->height = max(height(node->left),height(node->right)) + 1; 74 | l->height = max(height(l->left),height(l->right)) + 1; 75 | 76 | return l; 77 | } 78 | 79 | Node *inserthelp(Node *node,int x){ 80 | 81 | int balance; 82 | if(node==NULL){ 83 | node = (Node *) malloc(sizeof(Node)); 84 | node->key = x; 85 | node->nodecountL = 0; 86 | node->nodecountR = 0; 87 | node->height = 0; 88 | node->left = NULL; 89 | node->right = NULL; 90 | return node; 91 | } 92 | if(x < node->key){ 93 | node->left = inserthelp(node->left,x); 94 | node->nodecountL++; 95 | } 96 | else{ 97 | node->right = inserthelp(node->right,x); 98 | node->nodecountR++; 99 | } 100 | node->height = max(height(node->left),height(node->right)) + 1; 101 | balance = height(node->left) - height(node->right); 102 | if(balance > 1 && x < (node->left->key)){ 103 | node = rightRotate(node); 104 | } 105 | else if(balance < -1 && x > (node->right->key)){ 106 | node = leftRotate(node); 107 | } 108 | else if(balance > 1 && x > (node->left->key)){ 109 | node->left = leftRotate(node->left); 110 | node = rightRotate(node); 111 | } 112 | else if(balance < -1 && x < (node->right->key)){ 113 | node->right = rightRotate(node->right); 114 | node = leftRotate(node); 115 | } 116 | 117 | return node; 118 | 119 | } 120 | 121 | void insert(BST *bst,int x){ 122 | 123 | bst->root = inserthelp(bst->root,x); 124 | } 125 | 126 | int findhelp(Node *node,int x,int value){ 127 | 128 | if(node==NULL) return -1; 129 | if(node->key == x) return (value+(node->nodecountL)+1); 130 | else if(x > node->key){ 131 | value+= (total(node->left) + 1); 132 | return findhelp(node->right,x,value); 133 | } 134 | else{ 135 | return findhelp(node->left,x,value); 136 | } 137 | } 138 | 139 | int find(BST *bst,int x){ 140 | 141 | return findhelp(bst->root,x,0); 142 | } 143 | 144 | Node *apagar(Node *node){ 145 | 146 | if(node==NULL) return NULL; 147 | node->left = apagar(node->left); 148 | node->right = apagar(node->right); 149 | free(node); 150 | return NULL; 151 | } 152 | 153 | void clear(BST *bst){ 154 | 155 | bst->root = apagar(bst->root); 156 | } 157 | 158 | 159 | int main(){ 160 | 161 | BST *bst; 162 | int q,op,x,i,st; 163 | 164 | bst = create_bst(); 165 | scanf("%d",&q); 166 | for(int i=0;i> edge; 5 | vector> sat; 6 | vector> level; 7 | vector> dead; 8 | vector isSource; 9 | vector isSink; 10 | 11 | bool hasFlow(int x, int y){ 12 | return sat[x][y] != 0; 13 | } 14 | 15 | int getReverseEdge(int x, int y, int k){ 16 | int ny = y + (k - MAX_DIST); 17 | if(x == 0) return -1; 18 | if(ny < 0 || ny >= M) return -1; 19 | 20 | int b = (1<<(MAX_DIST - (k - MAX_DIST))); 21 | if(((sat[x-1][ny])&b) == 0) return -1; 22 | 23 | return ny; 24 | } 25 | 26 | int getNormalEdge(int x, int y, int k){ 27 | int ny = y + (k - MAX_DIST); 28 | if(x == N-1) return -1; 29 | if(ny < 0 || ny >= M) return -1; 30 | 31 | int b = (1< q; 71 | for(int j=0;j 3 | using namespace std; 4 | #define PI 3.14159265359 5 | #define PREC 0.00001 6 | typedef long double ldb; 7 | #define asp "" 8 | #define aps '' 9 | #define one 1 10 | #define two 2 11 | #define dif != 12 | 13 | typedef struct{ 14 | 15 | ldb x; 16 | ldb y; 17 | ldb raio; 18 | 19 | }circle; 20 | 21 | typedef struct{ 22 | 23 | ldb x; 24 | ldb y; 25 | 26 | }vetor; 27 | 28 | vector g; 29 | // printf(""); 30 | 31 | ldb escalar(vetor A, vetor B){ 32 | 33 | ldb ans = ((A.x * B.x) + (A.y * B.y)); 34 | return ans; 35 | } 36 | 37 | ldb modulo(vetor A){ 38 | 39 | ldb ans = sqrt((A.x * A.x) + (A.y*A.y)); 40 | return ans; 41 | } 42 | 43 | ldb toDegree(ldb rad){ 44 | 45 | ldb ans = ((180.0*rad)/PI); 46 | return ans; 47 | } 48 | 49 | ldb toRad(ldb degree){ 50 | 51 | while(degree < 0.0) degree+= 360.0; 52 | while(degree > 360.0) degree -= 360.0; 53 | if(degree > 180.0) degree = 360.0 - degree; 54 | ldb ans = ((degree*PI)/(180.0)); 55 | return ans; 56 | } 57 | 58 | void leitor(){ 59 | 60 | circle aux; 61 | //printf("Digite a coordenada do centro 1:\n"); 62 | scanf("%Lf %Lf",&aux.x,&aux.y); 63 | printf("%Lf %Lf\n",aux.x,aux.y); 64 | //printf("Digite o raio 1:\n"); 65 | scanf("%Lf",&aux.raio); 66 | g.push_back(aux); 67 | //printf("Digite a coordenada do centro 2:\n"); 68 | scanf("%Lf %Lf",&aux.x,&aux.y); 69 | printf("%Lf %Lf\n",aux.x,aux.y); 70 | //printf("Digite o raio 2:\n"); 71 | scanf("%Lf",&aux.raio); 72 | g.push_back(aux); 73 | } 74 | 75 | int solve(ldb *ax,ldb *ay,ldb *bx,ldb *by,int pivoA,int pivoB){ 76 | 77 | ldb angle; 78 | vetor Padrao = {1,0}; 79 | vetor atual; 80 | // mesmo centro 81 | if(g[pivoA].x == g[pivoB].x && g[pivoA].y == g[pivoB].y) return 0; 82 | 83 | atual.x = g[pivoB].x - g[pivoA].x; 84 | atual.y = g[pivoB].y - g[pivoA].y; 85 | 86 | angle = toDegree(acos(escalar(Padrao,atual)/(modulo(Padrao)*modulo(atual)))); 87 | 88 | // /printf("angle is %0.Lf\n",angle); 89 | 90 | int signaly; 91 | int signalx; 92 | if(atual.y < Padrao.y){ 93 | signaly = -1; 94 | } 95 | else signaly = 1; 96 | 97 | if(atual.x < Padrao.x){ 98 | signalx = -1; 99 | } 100 | else{ 101 | signalx = 1; 102 | } 103 | 104 | vetor A; 105 | vetor B; 106 | 107 | B.x = g[pivoB].x; 108 | B.y = g[pivoB].y; 109 | 110 | A.x = g[pivoA].x + (g[pivoA].raio * cos(toRad(angle))); 111 | A.y = g[pivoA].y + ((ldb)signaly * g[pivoA].raio * sin(toRad(angle))); 112 | 113 | vetor aux; 114 | aux.x = A.x - B.x; 115 | aux.y = A.y - B.y; 116 | 117 | if(modulo(aux) > (ldb)g[pivoB].raio) return 0; 118 | 119 | A.x = g[pivoA].x + (g[pivoA].raio * cos(toRad(angle+180.0))); 120 | A.y = g[pivoA].y + ((ldb)signaly * g[pivoA].raio * sin(toRad(angle+180.0))); 121 | aux.x = A.x - B.x; 122 | aux.y = A.y - B.y; 123 | if(modulo(aux) < (ldb)g[pivoB].raio) return 0; 124 | 125 | /// busca binaria em uma banda do circulo 126 | ldb s = angle; 127 | ldb e = angle - 180.0; 128 | ldb pivo; 129 | ldb step = 180.0; 130 | while(step > PREC){ 131 | if(s < 0) s += 360.0; 132 | if(s > 360.0) s -= 360.0; 133 | if(e < 0) e += 360.0; 134 | if(e > 360.0) e -= 360.0; 135 | step /= two; 136 | pivo = s-step; 137 | if(pivo < 0) pivo += 360.0; 138 | if(pivo > 360.0) pivo -= 360.0; 139 | 140 | if(pivo < 180.0) signaly = one; 141 | else signaly = -1; 142 | if(pivo > 90 && pivo < 270) signalx = -1; 143 | else signalx = 1; 144 | 145 | A.x = g[pivoA].x + (g[pivoA].raio * cos(toRad(pivo))); 146 | A.y = g[pivoA].y + ((ldb)signaly * g[pivoA].raio * sin(toRad(pivo))); 147 | aux.x = A.x - B.x; 148 | aux.y = A.y - B.y; 149 | 150 | if(modulo(aux) > (ldb)g[pivoB].raio){ 151 | e = pivo; 152 | } 153 | else{ 154 | s = pivo; 155 | } 156 | } 157 | //printf("angle is %0.Lf\n",angle); 158 | //printf("angle is %0.Lf\n",pivo); 159 | //printf("%0.Lf == %0.Lf\n",cos(toRad(45)),cos(toRad(135))); 160 | 161 | *ax = A.x; *ay = A.y; 162 | //printf("angle is %0.Lf\n",angle); 163 | ldb diff = angle + fabs(360.0 - pivo); 164 | //printf("angle is %0.Lf\n",diff); 165 | while(diff > 360.0) diff-=360.0; 166 | pivo = angle + diff; 167 | while(pivo > 360.0) pivo -= 360.0; 168 | 169 | if(pivo < 180.0) signaly = one; 170 | else signaly = -1; 171 | if(pivo > 90 && pivo < 270) signalx = -1; 172 | else signalx = 1; 173 | //printf("angle is %0.Lf\n",pivo); 174 | 175 | A.x = g[pivoA].x + (g[pivoA].raio * cos(toRad(pivo))); 176 | A.y = g[pivoA].y + ((ldb)signaly * g[pivoA].raio * sin(toRad(pivo))); 177 | 178 | *bx = A.x; *by = A.y; 179 | 180 | return two; 181 | } 182 | 183 | int main(){ 184 | 185 | ldb ax,ay,bx,by; 186 | leitor(); 187 | int ret = solve(&ax,&ay,&bx,&by,0,1); 188 | 189 | if(ret == 0){ 190 | printf("Nao ha interseccoes nas circunferencias dadas\n"); 191 | } 192 | else if(ret == one){ 193 | printf("Existe apenas um ponto que intercepta a circunferencia: "); 194 | printf("(%Lf, %Lf)\n",ax,ay); 195 | } 196 | else{ 197 | printf("Os dois pontos sao: (%.3Lf,%.3Lf) e (%.3Lf,%.3Lf)\n",ax,ay,bx,by); 198 | } 199 | 200 | return 0; 201 | } 202 | -------------------------------------------------------------------------------- /non-deterministic/HASHCODE_2022/Mentorship_and_Teamwork.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 5 | 6 | typedef pair ii; 7 | typedef pair> iv; 8 | 9 | int C, P; 10 | 11 | vector id_name; 12 | vector id_project; 13 | 14 | map skill_id; 15 | vector id_skill; 16 | 17 | vector> skills; 18 | vector> roles; 19 | 20 | vector pj_duration; 21 | vector pj_score; 22 | vector pj_deadline; 23 | 24 | void readInput(){ 25 | 26 | cin >> C >> P; 27 | 28 | for(int i=0;i> name; 31 | 32 | id_name.push_back(name); 33 | 34 | int n; 35 | cin >> n; 36 | 37 | vector skill_contrib; 38 | 39 | for(int j=0;j> skill_name; 42 | int l; 43 | cin >> l; 44 | 45 | if(skill_id.count(skill_name) == 0){ 46 | skill_id[skill_name] = id_skill.size(); 47 | id_skill.push_back(skill_name); 48 | } 49 | 50 | int id = skill_id[skill_name]; 51 | 52 | skill_contrib.push_back({id, l}); 53 | } 54 | 55 | skills.push_back(skill_contrib); 56 | } 57 | 58 | for(int i=0;i> name; 61 | 62 | id_project.push_back(name); 63 | 64 | int d; 65 | cin >> d; 66 | pj_duration.push_back(d); 67 | 68 | int s; 69 | cin >> s; 70 | pj_score.push_back(s); 71 | 72 | int bbefore; 73 | cin >> bbefore; 74 | pj_deadline.push_back(bbefore); 75 | 76 | int r; 77 | cin >> r; 78 | 79 | vector roles_pj; 80 | 81 | for(int j=0;j> name; 84 | 85 | int l; 86 | cin >> l; 87 | 88 | if(skill_id.count(name) == 0){ 89 | skill_id[name] = id_skill.size(); 90 | id_skill.push_back(name); 91 | } 92 | 93 | int id = skill_id[name]; 94 | 95 | roles_pj.push_back({id, l}); 96 | } 97 | 98 | roles.push_back(roles_pj); 99 | } 100 | } 101 | 102 | vector naive(){ 103 | 104 | vector ret; 105 | 106 | for(int i=0;i " << P-1-i << endl; 108 | vector assignes; 109 | 110 | set all; 111 | 112 | for(int j=0;j(0, C-1)(rng); 114 | 115 | if(all.find(id) != all.end()){ 116 | j--; 117 | continue; 118 | } 119 | all.insert(id); 120 | assignes.push_back(id); 121 | } 122 | 123 | ret.push_back({i, assignes}); 124 | } 125 | 126 | shuffle(ret.begin(), ret.end(), rng); 127 | 128 | return ret; 129 | } 130 | 131 | bool change_project; 132 | int p_id; 133 | int c_pos; 134 | int old_id; 135 | int p_id1; 136 | int p_id2; 137 | 138 | void reverseState(vector &S){ 139 | 140 | if(change_project == false){ 141 | S[p_id].second[c_pos] = old_id; 142 | } 143 | else{ 144 | swap(S[p_id1], S[p_id2]); 145 | } 146 | } 147 | 148 | void getneighborhood(vector &S){ 149 | 150 | double choice = uniform_real_distribution(0, 1.0)(rng); 151 | double rate = 0.5; 152 | 153 | if(choice < rate){ 154 | change_project = false; 155 | p_id = uniform_int_distribution(0, P-1)(rng); 156 | 157 | c_pos = uniform_int_distribution(0, (int)S[p_id].second.size() - 1)(rng); 158 | old_id = S[p_id].second[c_pos]; 159 | int nw_id = uniform_int_distribution(0, C-1)(rng); 160 | 161 | S[p_id].second[c_pos] = nw_id; 162 | } 163 | else{ 164 | change_project = true; 165 | p_id1 = uniform_int_distribution(0, P-1)(rng); 166 | p_id2 = uniform_int_distribution(0, P-1)(rng); 167 | 168 | swap(S[p_id1], S[p_id2]); 169 | } 170 | } 171 | 172 | long long score(vector &S){ 173 | 174 | long long ret = 0; 175 | map add; 176 | map freeDay; 177 | 178 | for(iv &project: S){ 179 | int pid = project.first; 180 | 181 | map team; 182 | 183 | bool canDo = true; 184 | 185 | vector needHelp; 186 | vector improveSkill; 187 | 188 | int start_at = 0; 189 | 190 | for(int i=0;i &S){ 248 | 249 | map add; 250 | map freeDay; 251 | 252 | int total = 0; 253 | 254 | for(iv &project: S){ 255 | int pid = project.first; 256 | 257 | map team; 258 | 259 | bool canDo = true; 260 | 261 | vector needHelp; 262 | vector improveSkill; 263 | 264 | int start_at = 0; 265 | 266 | for(int i=0;i team; 330 | 331 | bool canDo = true; 332 | 333 | vector needHelp; 334 | vector improveSkill; 335 | 336 | int start_at = 0; 337 | 338 | for(int i=0;i S0 = naive(); 409 | int M = 10000; 410 | int P = 1000; 411 | int L = 100; 412 | double alpha = 0.995; 413 | 414 | vector S = S0; 415 | double T0 = 100000.0; 416 | double T = T0; 417 | 418 | int nSucesso = 1; 419 | 420 | long long score_s = score(S); 421 | 422 | for(int i=0;i<=M && nSucesso > 0;i++){ 423 | nSucesso = 0; 424 | 425 | cerr << "iter: " << i << "/" << M << endl; 426 | cerr << "temp: " << T << endl; 427 | cerr << "score: " << score_s << endl; 428 | cerr << "-------------------------" << endl; 429 | 430 | for(int j=0;j<=P && nSucesso<=L;j++){ 431 | getneighborhood(S); 432 | long long score_si = score(S); 433 | long long delta = score_s - score_si; 434 | 435 | // energia negativa -> melhor solucao 436 | if(delta <= 0.0 || exp(-delta/T) > uniform_real_distribution(0, 1.0)(rng)){ 437 | score_s = score_si; 438 | nSucesso++; 439 | } 440 | else{ 441 | reverseState(S); 442 | } 443 | } 444 | T = T*alpha; 445 | } 446 | 447 | cerr << "Final Score: " << score_s << endl; 448 | printSolution(S); 449 | } 450 | 451 | int main(){ 452 | 453 | ios::sync_with_stdio(0); 454 | cin.tie(0); 455 | cout.tie(0); 456 | 457 | cerr << "reading input..." << endl; 458 | readInput(); 459 | cerr << "call sAnnealing..." << endl; 460 | sAnnealing(); 461 | } 462 | -------------------------------------------------------------------------------- /non-deterministic/HASHCODE_2022/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | typedef long long ll; 6 | typedef pair ii; 7 | 8 | const int MAXV = 10000; 9 | const int INF = 1e9; 10 | 11 | const int dr[4] = { 0, 1, 0, -1 }; 12 | const int dc[4] = { 1, 0, -1, 0 }; 13 | 14 | int R, C, S; 15 | vector length; 16 | vector> isWormhole; 17 | vector> wormholes; 18 | vector> grid; 19 | vector> occupied; 20 | 21 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 22 | 23 | void read_input(){ 24 | cin >> C >> R >> S; 25 | 26 | length.resize(S); 27 | for(int i = 0; i < S; i++) 28 | cin >> length[i]; 29 | 30 | grid.assign(R, vector(C)); 31 | isWormhole.assign(R, vector(C, false)); 32 | occupied.assign(R, vector(C, false)); 33 | 34 | for(int i = 0; i < R; i++){ 35 | for (int j = 0; j < C; j++) { 36 | string number; cin >> number; 37 | if (number != "*") grid[i][j] = stoi(number); 38 | else grid[i][j] = 0, isWormhole[i][j] = true, wormholes.emplace_back(i, j); 39 | } 40 | } 41 | } 42 | 43 | ll score(vector &snake){ 44 | ll ret = 0; 45 | 46 | for(int i=0;i< (int) snake.size();i++){ 47 | int x = snake[i].first; 48 | int y = snake[i].second; 49 | 50 | ret += ll(grid[x][y]); 51 | } 52 | 53 | return ret; 54 | } 55 | 56 | ii get_new_random_pos() { 57 | int row = uniform_int_distribution(0, R - 1)(rng); 58 | int col = uniform_int_distribution(0, C - 1)(rng); 59 | return make_pair(row, col); 60 | } 61 | 62 | bool valid(ii pos) { 63 | return !occupied[pos.first][pos.second]; 64 | } 65 | 66 | ii get_new_random_wormhole() { 67 | int size = wormholes.size(); 68 | 69 | return wormholes[uniform_int_distribution(0, size - 1)(rng)]; 70 | } 71 | 72 | void clear_path(vector &positions) { 73 | for(auto auto_p: positions){ 74 | int row = auto_p.first; 75 | int col = auto_p.second; 76 | occupied[row][col] = false; 77 | } 78 | } 79 | 80 | vector get_new_random_path(int id) { 81 | const int max_attempts = 10; 82 | const double prob_choose = 1.0; 83 | 84 | if (uniform_real_distribution(0, 1.0)(rng) > prob_choose) 85 | return vector(); 86 | 87 | int attempts = 0; 88 | ii initial = get_new_random_pos(); 89 | 90 | while ((!valid(initial) || isWormhole[initial.first][initial.second]) && attempts < max_attempts) 91 | initial = get_new_random_pos(), attempts++; 92 | 93 | if (!valid(initial) || isWormhole[initial.first][initial.second]) 94 | return vector(); 95 | 96 | ii curr = initial; 97 | vector positions(1, initial); 98 | occupied[curr.first][curr.second] = true; 99 | bool entry = false; 100 | 101 | for (int i = 1; i < length[id]; i++) { 102 | if (isWormhole[curr.first][curr.second] && entry) { 103 | if ((int) wormholes.size() == 1) { 104 | clear_path(positions); 105 | return vector(); 106 | } 107 | 108 | ii newPos; 109 | do newPos = get_new_random_wormhole(); 110 | while (newPos == curr); 111 | 112 | positions.push_back(newPos); 113 | curr = newPos; 114 | entry = false; 115 | } else { 116 | ii newPos; 117 | int dir, chosen = 0; 118 | 119 | vector dirs = {0, 1, 2, 3}; 120 | //(dirs.begin(), dirs.end(), rng); 121 | 122 | for(auto dir: dirs){ 123 | newPos = make_pair((curr.first + dr[dir] + R) % R, (curr.second + dc[dir] + C) % C); 124 | if(valid(newPos)) break; 125 | } 126 | 127 | /*do { 128 | dir = uniform_int_distribution(0, 3)(rng); 129 | newPos = make_pair((curr.first + dr[dir] + R) % R, (curr.second + dc[dir] + C) % C); 130 | chosen |= (1 << dir); 131 | } while (!valid(newPos) && chosen != 15*/ 132 | 133 | if (!valid(newPos)) { 134 | clear_path(positions); 135 | return vector(); 136 | } 137 | 138 | if (isWormhole[newPos.first][newPos.second]) entry = true; 139 | else occupied[newPos.first][newPos.second] = true; 140 | 141 | positions.push_back(newPos); 142 | curr = newPos; 143 | } 144 | } 145 | 146 | if (isWormhole[curr.first][curr.second]) { 147 | clear_path(positions); 148 | return vector(); 149 | } 150 | 151 | return positions; 152 | } 153 | 154 | vector> get_initial_paths() { 155 | vector> paths; 156 | paths.resize(S); 157 | return paths; 158 | 159 | vector ids; 160 | for(int i=0;i& snake_path) { 176 | for(auto& auto_p : snake_path) { 177 | int x = auto_p.first; 178 | int y = auto_p.second; 179 | if(isWormhole[x][y]) continue; 180 | occupied[x][y] = true; 181 | } 182 | } 183 | 184 | ll solution_score(const vector>& S) { 185 | ll ret = 0; 186 | for(auto snake_path : S) { 187 | ret += score(snake_path); 188 | } 189 | return ret; 190 | } 191 | 192 | void undo_snake_path(const vector& snake_path) { 193 | for(auto& auto_p : snake_path) { 194 | auto x = auto_p.first; 195 | auto y = auto_p.second; 196 | if(isWormhole[x][y]) continue; 197 | occupied[x][y] = false; 198 | } 199 | } 200 | pair> get_neighborhood(const vector>& snakes) { 201 | int S = (int)snakes.size(); 202 | int id = uniform_int_distribution(0, S - 1)(rng); 203 | undo_snake_path(snakes[id]); 204 | auto new_path = get_new_random_path(id); 205 | undo_snake_path(new_path); 206 | return make_pair(id, new_path); 207 | } 208 | 209 | map, char> direction; 210 | 211 | void init_directions() { 212 | direction[{1, 0}] = 'D'; 213 | direction[{0, 1}] = 'R'; 214 | direction[{R - 1, 0}] = 'U'; 215 | direction[{0, C - 1}] = 'L'; 216 | } 217 | 218 | void print_solution(const vector>& S) { 219 | cout << "#####################\n"; 220 | for(const auto& snake_path : S) { 221 | if(snake_path.empty()) { 222 | cout << '\n'; 223 | continue; 224 | } 225 | cout << snake_path[0].second << ' ' << snake_path[0].first << ' '; 226 | int len = (int)snake_path.size(); 227 | bool entry = false; 228 | 229 | for(int i = 1; i < len; ++i) { 230 | int dx = (snake_path[i].first - snake_path[i - 1].first + R) % R; 231 | int dy = (snake_path[i].second - snake_path[i - 1].second + C) % C; 232 | 233 | if (isWormhole[snake_path[i].first][snake_path[i].second] && !entry) { 234 | if (isWormhole[snake_path[i - 1].first][snake_path[i - 1].second]) { 235 | entry = true; 236 | cout << snake_path[i].second << " " << snake_path[i].first << " "; 237 | continue; 238 | } 239 | } 240 | 241 | cout << direction[{dx, dy}] << ' '; 242 | entry = false; 243 | } 244 | cout << '\n'; 245 | } 246 | } 247 | 248 | void sAnnealing(){ 249 | // pseudo-code 250 | /************* setar isso aqui inicialmente 251 | S0 = estado inicial 252 | M = numero maximo de iteracoes 253 | P = pertubacoes por iteracao 254 | L = numero maximo de sucessos por iteracoes 255 | alpha = fator de reducao da temperatura 256 | ******************************************/ 257 | double TEMP_INICIAL = 1000000.0; 258 | double alpha = 0.995; 259 | int M = 50000; 260 | int P = 10000; 261 | int print_per_iterations = M / 100; 262 | double barreira = 1e-5; 263 | 264 | vector> S = get_initial_paths(); 265 | ll total_score = solution_score(S); 266 | double T0 = TEMP_INICIAL; 267 | double T = T0; 268 | 269 | ll last = 1; 270 | int stoped = 0; 271 | 272 | for(int i=0;i<=M;i++){ 273 | int failed_state = 0; 274 | int negatives_deltas = 0; 275 | int negative_paths = 0; 276 | int null_paths = 0; 277 | 278 | for(int j=0;j<=P;j++){ 279 | auto auto_p = get_neighborhood(S); 280 | auto snake_id = auto_p.first; 281 | auto new_path = auto_p.second; 282 | 283 | ll score_new_path = score(new_path); 284 | if(score_new_path < 0){ 285 | score_new_path = 0; 286 | new_path.clear(); 287 | } 288 | 289 | ll delta = score(S[snake_id]) - score_new_path; 290 | 291 | if(score_new_path < 0) negative_paths++; 292 | if(new_path.size() == 0) null_paths++; 293 | 294 | if(delta > 0) negatives_deltas++; 295 | 296 | // energia negativa -> melhor solucao 297 | if(delta <= 0.0 || exp(-delta/T) > uniform_real_distribution(0, 1.0)(rng)){ 298 | mark_snake_path(new_path); 299 | S[snake_id].swap(new_path); 300 | total_score -= delta; 301 | if(delta > 0) failed_state++; 302 | } else { 303 | mark_snake_path(S[snake_id]); 304 | } 305 | } 306 | T = T*alpha; 307 | if (T < barreira) { 308 | print_solution(S); 309 | break; 310 | } 311 | 312 | cerr << "----------------------------------------------------" << '\n'; 313 | cerr << "total_score: " << total_score << '\n'; 314 | cerr << "temperatura: " << T << '\n'; 315 | cerr << "iteracoes: " << i << "/" << M << "\n"; 316 | if(negatives_deltas == 0) negatives_deltas++; 317 | cerr << "max_local factor: " << (double)failed_state/negatives_deltas << '\n'; 318 | 319 | double aux = (double) negative_paths / (P+1); 320 | cerr << "negative_paths = " << aux << '\n'; 321 | aux = (double) null_paths / (P+1); 322 | cerr << "null_paths = " << aux << '\n'; 323 | 324 | if(last == total_score){ 325 | stoped++; 326 | } 327 | else{ 328 | stoped = 0; 329 | } 330 | 331 | if(stoped >= 25) break; 332 | 333 | double perc = (double) total_score / last - 1.0; 334 | perc *= 100; 335 | cerr << "crescimento = " << perc << "%\n"; 336 | last = total_score; 337 | 338 | if (i % print_per_iterations == 0){ 339 | print_solution(S); 340 | } 341 | } 342 | print_solution(S); 343 | } 344 | 345 | int main(){ 346 | ios::sync_with_stdio(0); 347 | cin.tie(0); 348 | 349 | read_input(); 350 | init_directions(); 351 | sAnnealing(); 352 | } 353 | --------------------------------------------------------------------------------