Skip to content

Commit c75eefd

Browse files
chore: update minified library versions
1 parent 6cda92f commit c75eefd

File tree

18 files changed

+22
-23
lines changed

18 files changed

+22
-23
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#ifndef CP_ALGO_GEOMETRY_CLOSEST_PAIR_HPP
22
#define CP_ALGO_GEOMETRY_CLOSEST_PAIR_HPP
33
#include "../random/rng.hpp"
4+
#include "../util/big_alloc.hpp"
45
#include "point.hpp"
56
#include <vector>
67
#include <map>
7-
namespace cp_algo::geometry{template<typename ftype>auto closest_pair(std::vector<point_t<ftype>>const&r){using point=point_t<ftype>;size_t n=size(r);int64_t md=1e18;for(size_t i=0;i<n/100;i++){auto A=random::rng()%n;auto B=random::rng()%n;if(A!=B){md=std::min(md,norm(r[A]-r[B]));if(md==0){return std::pair{A,B};}}}std::map<point,std::vector<size_t>>neigs;md=(int64_t)ceil(sqrt((double)md));for(size_t i=0;i<n;i++){neigs[r[i]/md].push_back(i);}size_t a=0,b=1;md=norm(r[a]-r[b]);for(auto&[p,id]:neigs){for(int dx:{-1,0,1}){for(int dy:{-1,0,1}){auto pp=p+point{dx,dy};if(!neigs.count(pp)){continue;}for(size_t i:neigs[pp]){for(size_t j:id){if(j==i){break;}int64_t cur=norm(r[i]-r[j]);if(cur<md){md=cur;a=i;b=j;}}}}}}return std::pair{a,b};}}
8+
namespace cp_algo::geometry{auto closest_pair(auto const&r){using point=std::decay_t<decltype(r[0])>;size_t n=size(r);int64_t md=1e18;for(size_t i=0;i<n/100;i++){auto A=random::rng()%n;auto B=random::rng()%n;if(A!=B){md=std::min(md,norm(r[A]-r[B]));if(md==0){return std::pair{A,B};}}}std::map<point,big_vector<size_t>>neigs;md=(int64_t)ceil(sqrt((double)md));for(size_t i=0;i<n;i++){neigs[r[i]/md].push_back(i);}size_t a=0,b=1;md=norm(r[a]-r[b]);for(auto&[p,id]:neigs){for(int dx:{-1,0,1}){for(int dy:{-1,0,1}){auto pp=p+point{dx,dy};if(!neigs.count(pp)){continue;}for(size_t i:neigs[pp]){for(size_t j:id){if(j==i){break;}int64_t cur=norm(r[i]-r[j]);if(cur<md){md=cur;a=i;b=j;}}}}}}return std::pair{a,b};}}
89
#endif
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#ifndef CP_ALGO_GEOMETRY_CONVEX_HULL_HPP
22
#define CP_ALGO_GEOMETRY_CONVEX_HULL_HPP
33
#include "point.hpp"
4+
#include "../util/big_alloc.hpp"
45
#include <algorithm>
56
#include <utility>
67
#include <vector>
78
#include <ranges>
8-
namespace cp_algo::geometry{template<typename ftype>std::vector<point_t<ftype>>convex_hull(std::vector<point_t<ftype>>r){using point=point_t<ftype>;std::ranges::sort(r);if(size(r)<=1||r[0]==r.back()){return empty(r)?r:std::vector{r[0]};}std::vector<point>hull={r[0]};for(int half:{0,1}){size_t base=size(hull);for(auto it:std::views::drop(r,1)){while(size(hull)>=base+1){point a=hull.back();if(point::ccw(it-a,end(hull)[-2]-a)){break;}else{hull.pop_back();}}hull.push_back(it);}std::ranges::reverse(r);std::ignore=half;}hull.pop_back();return hull;}}
9+
namespace cp_algo::geometry{auto convex_hull(auto r){using point=std::decay_t<decltype(r[0])>;std::ranges::sort(r);if(size(r)<=1||r[0]==r.back()){return empty(r)?big_vector<point>{}:big_vector{r[0]};}big_vector<point>hull={r[0]};for(int half:{0,1}){size_t base=size(hull);for(auto it:std::views::drop(r,1)){while(size(hull)>=base+1){point a=hull.back();if(point::ccw(it-a,end(hull)[-2]-a)){break;}else{hull.pop_back();}}hull.push_back(it);}std::ranges::reverse(r);std::ignore=half;}hull.pop_back();return hull;}}
910
#endif

cp-algo/min/graph/euler.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#ifndef CP_ALGO_GRAPH_EULER_HPP
22
#define CP_ALGO_GRAPH_EULER_HPP
33
#include "base.hpp"
4+
#include "../util/big_alloc.hpp"
45
#include <algorithm>
56
#include <iostream>
67
#include <optional>
78
#include <utility>
89
#include <vector>
910
#include <stack>
10-
namespace cp_algo::graph{template<graph_type graph>std::optional<node_index>euler_start(graph const&g){std::vector<int>deg(g.n());std::optional<node_index>default_start=0;for(auto v:g.nodes()){for(auto e:g.outgoing(v)){deg[v]++;default_start=v;if constexpr(digraph_type<graph>){deg[g.edge(e).traverse(v)]--;}}}if constexpr(undirected_graph_type<graph>){for(auto&it:deg){it%=2;}}auto is_start=[&](int v){return deg[v]>0;};auto starts=std::ranges::count_if(g.nodes(),is_start);auto need_starts=undirected_graph_type<graph>?2:1;if(starts>need_starts){return std::nullopt;}else if(starts==need_starts){auto start=*std::ranges::find_if(g.nodes(),is_start);if(deg[start]==1){return start;}else{return std::nullopt;}}return default_start;}template<graph_type graph>std::deque<edge_index>try_euler_trail(graph const&g,node_index v0){std::deque<edge_index>trail;enum state{unvisited,visited};std::vector<state>state(g.m());auto const&adj=g.incidence_lists();auto head=adj.head;struct stack_frame{edge_index ep;node_index v;};std::stack<stack_frame>stack;stack.push({-1,v0});while(!empty(stack)){auto[ep,v]=stack.top();bool found_edge=false;while(head[v]!=0){auto e=adj.data[std::exchange(head[v],adj.next[head[v]])];if(state[e]==unvisited){state[e]=visited;stack.push({e,g.edge(e).traverse(v)});found_edge=true;break;}}if(!found_edge){stack.pop();if(~ep){trail.push_front(ep);}}}return trail;}template<graph_type graph>std::optional<std::pair<node_index,std::deque<edge_index>>>euler_trail(graph const&g){auto v0=euler_start(g);if(!v0){return std::nullopt;}auto result=try_euler_trail(g,*v0);if((edge_index)result.size()!=g.m()){return std::nullopt;}return{{*v0,std::move(result)}};}}
11+
namespace cp_algo::graph{template<graph_type graph>std::optional<node_index>euler_start(graph const&g){big_vector<int>deg(g.n());std::optional<node_index>default_start=0;for(auto v:g.nodes()){for(auto e:g.outgoing(v)){deg[v]++;default_start=v;if constexpr(digraph_type<graph>){deg[g.edge(e).traverse(v)]--;}}}if constexpr(undirected_graph_type<graph>){for(auto&it:deg){it%=2;}}auto is_start=[&](int v){return deg[v]>0;};auto starts=std::ranges::count_if(g.nodes(),is_start);auto need_starts=undirected_graph_type<graph>?2:1;if(starts>need_starts){return std::nullopt;}else if(starts==need_starts){auto start=*std::ranges::find_if(g.nodes(),is_start);if(deg[start]==1){return start;}else{return std::nullopt;}}return default_start;}template<graph_type graph>std::deque<edge_index>try_euler_trail(graph const&g,node_index v0){std::deque<edge_index>trail;enum state{unvisited,visited};big_vector<state>state(g.m());auto const&adj=g.incidence_lists();auto head=adj.head;struct stack_frame{edge_index ep;node_index v;};std::stack<stack_frame>stack;stack.push({-1,v0});while(!empty(stack)){auto[ep,v]=stack.top();bool found_edge=false;while(head[v]!=0){auto e=adj.data[std::exchange(head[v],adj.next[head[v]])];if(state[e]==unvisited){state[e]=visited;stack.push({e,g.edge(e).traverse(v)});found_edge=true;break;}}if(!found_edge){stack.pop();if(~ep){trail.push_front(ep);}}}return trail;}template<graph_type graph>std::optional<std::pair<node_index,std::deque<edge_index>>>euler_trail(graph const&g){auto v0=euler_start(g);if(!v0){return std::nullopt;}auto result=try_euler_trail(g,*v0);if((edge_index)result.size()!=g.m()){return std::nullopt;}return{{*v0,std::move(result)}};}}
1112
#endif

cp-algo/min/graph/mst.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
#include "../structures/dsu.hpp"
55
#include "../util/sort.hpp"
66
#include <algorithm>
7-
namespace cp_algo::graph{template<weighted_undirected_graph_type graph>std::pair<int64_t,std::vector<edge_index>>mst(graph const&g){struct edge{edge_index idx;node_index v;};std::vector<edge>edges;for(auto v:g.nodes()){for(auto e:g.outgoing(v)){if(v<g.edge(e).traverse(v)){edges.push_back({e,v});}}}radix_sort(edges,[&](auto e){return g.edge(e.idx).w;});structures::dsu me(g.n());int64_t total=0;std::vector<edge_index>mst;for(auto[idx,v]:edges){if(me.uni(v,g.edge(idx).traverse(v))){total+=g.edge(idx).w;mst.push_back(idx);}}return{total,mst};}}
7+
namespace cp_algo::graph{template<weighted_undirected_graph_type graph>std::pair<int64_t,big_vector<edge_index>>mst(graph const&g){struct edge{edge_index idx;node_index v;};big_vector<edge>edges;for(auto v:g.nodes()){for(auto e:g.outgoing(v)){if(v<g.edge(e).traverse(v)){edges.push_back({e,v});}}}radix_sort(edges,[&](auto e){return g.edge(e.idx).w;});structures::dsu me(g.n());int64_t total=0;big_vector<edge_index>mst;for(auto[idx,v]:edges){if(me.uni(v,g.edge(idx).traverse(v))){total+=g.edge(idx).w;mst.push_back(idx);}}return{total,mst};}}
88
#endif

cp-algo/min/graph/shortest_path.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
#include "base.hpp"
44
#include <algorithm>
55
#include <queue>
6-
namespace cp_algo::graph{struct shortest_path_context{std::vector<int64_t>dist;std::vector<edge_index>pre;static constexpr int64_t inf=1e18;shortest_path_context(int n):dist(n,inf),pre(n){}};struct dijkstra_context:shortest_path_context{struct que_t{int64_t dist;node_index v;bool operator<(que_t const&other)const{return dist>other.dist;}};std::priority_queue<que_t>pq;dijkstra_context(int n):shortest_path_context(n){}void push(node_index,edge_index,node_index v){pq.push({dist[v],v});}std::optional<node_index>next_node(){while(!empty(pq)){auto[dv,v]=pq.top();pq.pop();if(dv==dist[v]){return v;}}return std::nullopt;}};struct spfa_context:shortest_path_context{std::queue<node_index>que;std::vector<char>flags;static constexpr char in_queue=1;static constexpr char invalidated=2;spfa_context(int n):shortest_path_context(n),flags(n){}void push(node_index,edge_index,node_index v){if(!(flags[v]&in_queue)){que.push(v);flags[v]|=in_queue;}}std::optional<node_index>next_node(){while(!que.empty()){node_index v=que.front();que.pop();flags[v]&=~in_queue;if(!(flags[v]&invalidated)){return v;}}return std::nullopt;}};struct deep_spfa_context:spfa_context{struct traverse_edge{edge_index e;node_index v;};std::vector<std::basic_string<traverse_edge>>dependents;deep_spfa_context(int n):spfa_context(n),dependents(n){}void push(node_index u,edge_index e,node_index v){invalidate_subtree(v);dependents[u].push_back({e,v});flags[v]&=~invalidated;spfa_context::push(u,e,v);}void invalidate_subtree(node_index v){std::vector<node_index>to_invalidate={v};while(!empty(to_invalidate)){node_index u=to_invalidate.back();to_invalidate.pop_back();flags[u]|=invalidated;flags[u]&=~in_queue;for(auto[e,v]:dependents[u]){if(pre[v]==e){to_invalidate.push_back(v);}}dependents[u].clear();}}};template<typename Context,weighted_graph_type graph>Context sssp_impl(graph const&g,node_index s){Context context(g.n());context.dist[s]=0;context.pre[s]=-1;context.push(s,-1,s);while(auto ov=context.next_node()){node_index v=*ov;for(auto e:g.outgoing(v)){node_index u=g.edge(e).traverse(v);auto w=g.edge(e).w;if(context.dist[v]+w<context.dist[u]){context.dist[u]=context.dist[v]+w;context.pre[u]=e;context.push(v,e,u);}}}return context;}template<weighted_graph_type graph>shortest_path_context dijkstra(graph const&g,node_index s){return sssp_impl<dijkstra_context>(g,s);}template<weighted_graph_type graph>shortest_path_context spfa(graph const&g,node_index s){return sssp_impl<spfa_context>(g,s);}template<weighted_graph_type graph>shortest_path_context deep_spfa(graph const&g,node_index s){return sssp_impl<deep_spfa_context>(g,s);}template<weighted_graph_type graph>shortest_path_context single_source_shortest_path(graph const&g,node_index s){bool negative_edges=false;for(auto e:g.edges()){negative_edges|=e.w<0;}return negative_edges?deep_spfa(g,s):dijkstra(g,s);}std::vector<edge_index>recover_path(auto const&g,auto const&pre,node_index s,node_index t){std::vector<edge_index>path;node_index v=t;while(v!=s){path.push_back(pre[v]);v=g.edge(pre[v]).traverse(v);}std::ranges::reverse(path);return path;}template<weighted_graph_type graph>std::optional<std::pair<int64_t,std::vector<edge_index>>>shortest_path(graph const&g,node_index s,node_index t){auto[dist,pre]=single_source_shortest_path(g,s);if(dist[t]==shortest_path_context::inf){return std::nullopt;}return{{dist[t],recover_path(g,pre,s,t)}};}}
6+
namespace cp_algo::graph{struct shortest_path_context{big_vector<int64_t>dist;big_vector<edge_index>pre;static constexpr int64_t inf=1e18;shortest_path_context(int n):dist(n,inf),pre(n){}};struct dijkstra_context:shortest_path_context{struct que_t{int64_t dist;node_index v;bool operator<(que_t const&other)const{return dist>other.dist;}};std::priority_queue<que_t>pq;dijkstra_context(int n):shortest_path_context(n){}void push(node_index,edge_index,node_index v){pq.push({dist[v],v});}std::optional<node_index>next_node(){while(!empty(pq)){auto[dv,v]=pq.top();pq.pop();if(dv==dist[v]){return v;}}return std::nullopt;}};struct spfa_context:shortest_path_context{std::queue<node_index>que;big_vector<char>flags;static constexpr char in_queue=1;static constexpr char invalidated=2;spfa_context(int n):shortest_path_context(n),flags(n){}void push(node_index,edge_index,node_index v){if(!(flags[v]&in_queue)){que.push(v);flags[v]|=in_queue;}}std::optional<node_index>next_node(){while(!que.empty()){node_index v=que.front();que.pop();flags[v]&=~in_queue;if(!(flags[v]&invalidated)){return v;}}return std::nullopt;}};struct deep_spfa_context:spfa_context{struct traverse_edge{edge_index e;node_index v;};big_vector<std::basic_string<traverse_edge>>dependents;deep_spfa_context(int n):spfa_context(n),dependents(n){}void push(node_index u,edge_index e,node_index v){invalidate_subtree(v);dependents[u].push_back({e,v});flags[v]&=~invalidated;spfa_context::push(u,e,v);}void invalidate_subtree(node_index v){big_vector<node_index>to_invalidate={v};while(!empty(to_invalidate)){node_index u=to_invalidate.back();to_invalidate.pop_back();flags[u]|=invalidated;flags[u]&=~in_queue;for(auto[e,v]:dependents[u]){if(pre[v]==e){to_invalidate.push_back(v);}}dependents[u].clear();}}};template<typename Context,weighted_graph_type graph>Context sssp_impl(graph const&g,node_index s){Context context(g.n());context.dist[s]=0;context.pre[s]=-1;context.push(s,-1,s);while(auto ov=context.next_node()){node_index v=*ov;for(auto e:g.outgoing(v)){node_index u=g.edge(e).traverse(v);auto w=g.edge(e).w;if(context.dist[v]+w<context.dist[u]){context.dist[u]=context.dist[v]+w;context.pre[u]=e;context.push(v,e,u);}}}return context;}template<weighted_graph_type graph>shortest_path_context dijkstra(graph const&g,node_index s){return sssp_impl<dijkstra_context>(g,s);}template<weighted_graph_type graph>shortest_path_context spfa(graph const&g,node_index s){return sssp_impl<spfa_context>(g,s);}template<weighted_graph_type graph>shortest_path_context deep_spfa(graph const&g,node_index s){return sssp_impl<deep_spfa_context>(g,s);}template<weighted_graph_type graph>shortest_path_context single_source_shortest_path(graph const&g,node_index s){bool negative_edges=false;for(auto e:g.edges()){negative_edges|=e.w<0;}return negative_edges?deep_spfa(g,s):dijkstra(g,s);}big_vector<edge_index>recover_path(auto const&g,auto const&pre,node_index s,node_index t){big_vector<edge_index>path;node_index v=t;while(v!=s){path.push_back(pre[v]);v=g.edge(pre[v]).traverse(v);}std::ranges::reverse(path);return path;}template<weighted_graph_type graph>std::optional<std::pair<int64_t,big_vector<edge_index>>>shortest_path(graph const&g,node_index s,node_index t){auto[dist,pre]=single_source_shortest_path(g,s);if(dist[t]==shortest_path_context::inf){return std::nullopt;}return{{dist[t],recover_path(g,pre,s,t)}};}}
77
#endif

cp-algo/min/linalg/frobenius.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
#include <algorithm>
66
#include <vector>
77
#include <ranges>
8-
namespace cp_algo::linalg{enum frobenius_mode{blocks,full};template<frobenius_mode mode=blocks>auto frobenius_form(auto const&A){using matrix=std::decay_t<decltype(A)>;using vec_t=matrix::vec_t;using base=typename matrix::base;using base=matrix::base;using polyn=math::poly_t<base>;assert(A.n()==A.m());size_t n=A.n();std::vector<polyn>charps;std::vector<vec_t>basis,basis_init;while(size(basis)<n){size_t start=size(basis);auto generate_block=[&](auto x){while(true){vec_t y=x|vec_t::ei(n+1,size(basis));for(auto&it:basis){y.reduce_by(it);}y.normalize();if(std::ranges::count(y|std::views::take(n),base(0))==int(n)){return polyn(typename polyn::Vector(begin(y)+n,end(y)));}else{basis_init.push_back(x);basis.push_back(y);x=A.apply(x);}}};auto full_rec=generate_block(vec_t::random(n));if constexpr(mode==full){if(full_rec.mod_xk(start)!=polyn()){auto charp=full_rec.div_xk(start);auto x=basis_init[start];auto shift=full_rec/charp;for(int j=0;j<shift.deg();j++){x.add_scaled(basis_init[j],shift[j]);}basis.resize(start);basis_init.resize(start);full_rec=generate_block(x.normalize());}}charps.push_back(full_rec.div_xk(start));}if constexpr(mode==full){for(size_t i=0;i<n;i++){for(size_t j=i+1;j<n;j++){basis[i].reduce_by(basis[j]);}basis[i].normalize();}auto T=matrix(basis_init);auto Tinv=matrix(basis);std::ignore=Tinv.sort_classify(n);for(size_t i=0;i<n;i++){Tinv[i]=vec_t(Tinv[i]|std::views::drop(n)|std::views::take(n))*(base(1)/Tinv[i][i]);}return std::tuple{T,Tinv,charps};}else{return charps;}}template<typename base>auto with_frobenius(matrix<base>const&A,auto&&callback){auto[T,Tinv,charps]=frobenius_form<full>(A);std::vector<matrix<base>>blocks;for(auto charp:charps){matrix<base>block(charp.deg());auto xk=callback(charp);for(size_t i=0;i<block.n();i++){std::ranges::copy(xk.a,begin(block[i]));xk=xk.mul_xk(1)%charp;}blocks.push_back(block);}auto S=matrix<base>::block_diagonal(blocks);return Tinv*S*T;}template<typename base>auto frobenius_pow(matrix<base>const&A,uint64_t k){return with_frobenius(A,[k](auto const&charp){return math::poly_t<base>::xk(1).powmod(k,charp);});}};
8+
namespace cp_algo::linalg{enum frobenius_mode{blocks,full};template<frobenius_mode mode=blocks>auto frobenius_form(auto const&A){using matrix=std::decay_t<decltype(A)>;using vec_t=matrix::vec_t;using base=typename matrix::base;using base=matrix::base;using polyn=math::poly_t<base>;assert(A.n()==A.m());size_t n=A.n();big_vector<polyn>charps;big_vector<vec_t>basis,basis_init;while(size(basis)<n){size_t start=size(basis);auto generate_block=[&](auto x){while(true){vec_t y=x|vec_t::ei(n+1,size(basis));for(auto&it:basis){y.reduce_by(it);}y.normalize();if(std::ranges::count(y|std::views::take(n),base(0))==int(n)){return polyn(typename polyn::Vector(begin(y)+n,end(y)));}else{basis_init.push_back(x);basis.push_back(y);x=A.apply(x);}}};auto full_rec=generate_block(vec_t::random(n));if constexpr(mode==full){if(full_rec.mod_xk(start)!=polyn()){auto charp=full_rec.div_xk(start);auto x=basis_init[start];auto shift=full_rec/charp;for(int j=0;j<shift.deg();j++){x.add_scaled(basis_init[j],shift[j]);}basis.resize(start);basis_init.resize(start);full_rec=generate_block(x.normalize());}}charps.push_back(full_rec.div_xk(start));}if constexpr(mode==full){for(size_t i=0;i<n;i++){for(size_t j=i+1;j<n;j++){basis[i].reduce_by(basis[j]);}basis[i].normalize();}auto T=matrix(basis_init);auto Tinv=matrix(basis);std::ignore=Tinv.sort_classify(n);for(size_t i=0;i<n;i++){Tinv[i]=vec_t(Tinv[i]|std::views::drop(n)|std::views::take(n))*(base(1)/Tinv[i][i]);}return std::tuple{T,Tinv,charps};}else{return charps;}}template<typename base>auto with_frobenius(matrix<base>const&A,auto&&callback){auto[T,Tinv,charps]=frobenius_form<full>(A);big_vector<matrix<base>>blocks;for(auto charp:charps){matrix<base>block(charp.deg());auto xk=callback(charp);for(size_t i=0;i<block.n();i++){std::ranges::copy(xk.a,begin(block[i]));xk=xk.mul_xk(1)%charp;}blocks.push_back(block);}auto S=matrix<base>::block_diagonal(blocks);return Tinv*S*T;}template<typename base>auto frobenius_pow(matrix<base>const&A,uint64_t k){return with_frobenius(A,[k](auto const&charp){return math::poly_t<base>::xk(1).powmod(k,charp);});}};
99
#endif

0 commit comments

Comments
 (0)