teamnote default

This commit is contained in:
2026-06-03 09:20:51 +09:00
commit f50ed902fe
65 changed files with 6033 additions and 0 deletions

331
.gitignore vendored Normal file
View File

@@ -0,0 +1,331 @@
## Core latex/pdflatex auxiliary files:
*.aux
*.lof
*.log
*.lot
*.fls
*.out
*.toc
*.fmt
*.fot
*.cb
*.cb2
.*.lb
## Intermediate documents:
*.dvi
*.xdv
*-converted-to.*
# these rules might exclude image files for figures etc.
# *.ps
# *.eps
# *.pdf
## Generated if empty string is given at "Please type another file name for output:"
.pdf
## Bibliography auxiliary files (bibtex/biblatex/biber):
*.bbl
*.bbl-SAVE-ERROR
*.bcf
*.bcf-SAVE-ERROR
*.blg
*-blx.aux
*-blx.bib
*.run.xml
## Build tool auxiliary files:
*.fdb_latexmk
*.synctex
*.synctex(busy)
*.synctex.gz
*.synctex.gz(busy)
*.pdfsync
*.rubbercache
rubber.cache
## Build tool directories for auxiliary files
# latexrun
latex.out/
## Auxiliary and intermediate files from other packages:
# algorithms
*.alg
*.loa
# achemso
acs-*.bib
# amsthm
*.thm
# attachfile2
*.atfi
# beamer
*.nav
*.pre
*.snm
*.vrb
# changes
*.soc
*.loc
# comment
*.cut
# context
*.tuc
*.tui
*.tuo
# cprotect
*.cpt
# elsarticle (documentclass of Elsevier journals)
*.spl
# endnotes
*.ent
# fixme
*.lox
# feynmf/feynmp
*.mf
*.mp
*.t[1-9]
*.t[1-9][0-9]
*.tfm
#(r)(e)ledmac/(r)(e)ledpar
*.end
*.?end
*.[1-9]
*.[1-9][0-9]
*.[1-9][0-9][0-9]
*.[1-9]R
*.[1-9][0-9]R
*.[1-9][0-9][0-9]R
*.eledsec[1-9]
*.eledsec[1-9]R
*.eledsec[1-9][0-9]
*.eledsec[1-9][0-9]R
*.eledsec[1-9][0-9][0-9]
*.eledsec[1-9][0-9][0-9]R
# glossaries
*.acn
*.acr
*.glg
*.glg-abr
*.glo
*.glo-abr
*.gls
*.gls-abr
*.glsdefs
*.lzo
*.lzs
*.slg
*.slo
*.sls
# uncomment this for glossaries-extra (will ignore makeindex's style files!)
# *.ist
# gnuplot
*.gnuplot
*.table
# gnuplottex
*-gnuplottex-*
# gregoriotex
*.gaux
*.glog
*.gtex
# htlatex
*.4ct
*.4tc
*.idv
*.lg
*.trc
*.xref
# hypdoc
*.hd
# hyperref
*.brf
# knitr
*-concordance.tex
# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files
# *.tikz
*-tikzDictionary
# latexindent will create succesive backup files by default
#*.bak*
# listings
*.lol
# luatexja-ruby
*.ltjruby
# makeidx
*.idx
*.ilg
*.ind
# minitoc
*.maf
*.mlf
*.mlt
*.mtc[0-9]*
*.slf[0-9]*
*.slt[0-9]*
*.stc[0-9]*
# minted
_minted*
*.data.minted
*.pyg
# morewrites
*.mw
# newpax
*.newpax
# nomencl
*.nlg
*.nlo
*.nls
# pax
*.pax
# pdfpcnotes
*.pdfpc
# sagetex
*.sagetex.sage
*.sagetex.py
*.sagetex.scmd
# scrwfile
*.wrt
# spelling
*.spell.bad
*.spell.txt
# svg
svg-inkscape/
# sympy
*.sout
*.sympy
sympy-plots-for-*.tex/
# pdfcomment
*.upa
*.upb
# pythontex
*.pytxcode
pythontex-files-*/
# tcolorbox
*.listing
# thmtools
*.loe
# TikZ & PGF
*.dpth
*.md5
*.auxlock
# titletoc
*.ptc
# todonotes
*.tdo
# vhistory
*.hst
*.ver
# easy-todo
*.lod
# xcolor
*.xcp
# xmpincl
*.xmpi
# xindy
*.xdy
# xypic precompiled matrices and outlines
*.xyc
*.xyd
# endfloat
*.ttt
*.fff
# Latexian
TSWLatexianTemp*
## Editors:
# WinEdt
*.bak
*.sav
# latexindent.pl
*.bak[0-9]*
# Texpad
.texpadtmp
# LyX
*.lyx~
# Kile
*.backup
# gummi
.*.swp
# KBibTeX
*~[0-9]*
# TeXnicCenter
*.tps
# auto folder when using emacs and auctex
./auto/*
*.el
# expex forward references with \gathertags
*-tags.tex
# standalone packages
*.sta
# Makeindex log files
*.lpz
# xwatermark package
*.xwm
# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
# option is specified. Footnotes are the stored in a file with suffix Notes.bib.
# Uncomment the next line to have this generated file ignored.
#*Notes.bib

17
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,17 @@
{
"latex-workshop.latex.tools": [
{
"name": "latexmk",
"command": "latexmk",
"args": [
"-shell-escape",
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"-pdf",
"-outdir=%OUTDIR%",
"%DOC%"
],
"env": {}
}],
}

BIN
main.pdf Normal file

Binary file not shown.

1068
main.tex Normal file

File diff suppressed because it is too large Load Diff

12
source/DP/DnC.cpp Normal file
View File

@@ -0,0 +1,12 @@
//D[t][s...e]를 구해야 하고, j의 탐색 범위는 [l, r]
void f(int t, int s, int e, int l, int r){
if(s > e) return;
int m = s + e >> 1;
int opt = l;
for(int i=l; i<=r; i++){
if(D[t-1][opt] + C[opt][m] > D[t-1][i] + C[i][m]) opt = i;
}
D[t][m] = D[t-1][opt] + C[opt][m];
f(t, s, m-1, l, opt);
f(t, m+1, e, opt, r);
}

17
source/DP/LIS.cpp Normal file
View File

@@ -0,0 +1,17 @@
template<class I> vi lis(const vector<I>& S) {
if (S.empty()) return {};
vi prev(sz(S));
typedef pair<I, int> p;
vector<p> res;
rep(i,0,sz(S)) {
// change 0 -> i for longest non-decreasing subsequence
auto it = lower_bound(all(res), p{S[i], 0});
if (it == res.end()) res.emplace_back(), it = res.end()-1;
*it = {S[i], i};
prev[i] = it == res.begin() ? 0 : (it-1)->second;
}
int L = sz(res), cur = res.back().second;
vi ans(L);
while (L--) ans[L] = cur, cur = prev[cur];
return ans;
}

View File

@@ -0,0 +1,30 @@
struct Line {
mutable ll k, m, p;
bool operator<(const Line& o) const { return k < o.k; }
bool operator<(ll x) const { return p < x; }
};
struct LineContainer : multiset<Line, less<>> {
// (for doubles, use inf = 1/.0, div(a,b) = a/b)
static const ll inf = LLONG_MAX;
ll div(ll a, ll b) { // floored division
return a / b - ((a ^ b) < 0 && a % b); }
bool isect(iterator x, iterator y) {
if (y == end()) return x->p = inf, 0;
if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
else x->p = div(y->m - x->m, x->k - y->k);
return x->p >= y->p;
}
void add(ll k, ll m) {
auto z = insert({k, m, 0}), y = z++, x = y;
while (isect(y, z)) z = erase(z);
if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
while ((y = x) != begin() && (--x)->p >= y->p)
isect(x, erase(y));
}
ll query(ll x) {
assert(!empty());
auto l = *lower_bound(x);
return l.k * x + l.m;
}
};

View File

@@ -0,0 +1,38 @@
namespace LC
{
vll line;
int getline(ll c)
{
int k = 0, st = 20;
while(st+1)
{
int now = k+(1<<st); st--;
if(now >= line.size()) continue;
if(line[now].fi*c+line[now].se < line[now-1].fi*c+line[now-1].se) k = now;
}
return k;
}
void pushline(pll C)
{
while(line.size() >= 2)
{
pll A = line[line.size()-2];
pll B = line.back();
A = {A.fi-C.fi, A.se-C.se};
B = {B.fi-C.fi, B.se-C.se};
A.se = -A.se; B.se = -B.se;
if(A.fi<0) A = {-A.fi, -A.se};
if(B.fi<0) B = {-B.fi, -B.se};
if(A.se*B.fi >= B.se*A.fi) line.pop_back();
else break;
}
line.pb(C);
}
} // namespace LC

52
source/DP/SlopeTrick.cpp Normal file
View File

@@ -0,0 +1,52 @@
const int N = 1e6+7;
int arr[N];
priority_queue<int> pq;
ll ans = 0;
int main()
{
getint(n);
forr(i, n) scanf("%d", arr+i);
pq.push(arr[1]); int t=0; ll val = 0;
fors(i, 2, n)
{
t++;
int r = t + pq.top();
if(r <= arr[i]) pq.push(arr[i]-t);
else
{
pq.push(arr[i]-t); pq.push(arr[i]-t); pq.pop();
ans += r-arr[i];
}
}
printf("%lld", ans);
}
int arr[N];
priority_queue<int> pq;
int ans2[N];
int main()
{
getint(n);
forr(i, n) scanf("%d", arr+i);
pq.push(arr[1]); ll ans = 0;
ans2[1] = arr[1];
fors(i, 2, n)
{
int r = (i-1) + pq.top();
if(r <= arr[i]) pq.push(arr[i]-(i-1));
else
{
pq.push(arr[i]-(i-1)); pq.push(arr[i]-(i-1)); pq.pop();
ans += r-arr[i];
}
ans2[i] = pq.top() + (i-1);
}
fore(i, n-1, 1) ans2[i] = min(ans2[i], ans2[i+1]-1);
forr(i, n) printf("%d\n", ans2[i]);
}

22
source/DP/SoS.cpp Normal file
View File

@@ -0,0 +1,22 @@
int n = 20;
vector<int> a(1 << n);
// keeps track of the sum over subsets
// with a certain amount of matching bits in the prefix
vector<vector<int>> dp(1 << n, vector<int>(n));
vector<int> sos(1 << n);
for (int mask = 0; mask < (1 << n); mask++) {
dp[mask][-1] = a[mask];
for (int x = 0; x < n; x++) {
dp[mask][x] = dp[mask][x - 1];
if (mask & (1 << x)) { dp[mask][x] += dp[mask - (1 << x)][x - 1]; }
}
sos[mask] = dp[mask][n - 1];
}
////////////////////////////////////////////
D[i] i에
fors(d, 0, 19) fors(i,0,(1<<20)-1)
if(i & (1<<d)) D[i] += D[i^(1<<d)];
-> D[i] : sum of subset of mask i

9
source/DS/Fenwick.cpp Normal file
View File

@@ -0,0 +1,9 @@
ll tree[N];
void update(int i,ll x) {
while(i < N) tree[i] += x, i += i&-i;
}
int query(int i) {
ll s = 0;
while(i) s += tree[i], i -= i&-i;
return s;
}

47
source/DS/LiChaoTree.cpp Normal file
View File

@@ -0,0 +1,47 @@
const ll L = 1e9+7, inf = 2*L*L+7;
struct Line {
ll a, b;
ll operator()(ll x){return a*x+b;}
Line():a(0),b(-inf){}
Line(ll a, ll b):a(a), b(b){}
};
struct Node {ll l, r; Line v; Node():l(-1), r(-1), v(){}};
using LiChao = vector<Node>;
// add Line v in [l, r]
void update(LiChao& seg, Line v, ll l, ll r, ll s=-L, ll e=L, ll i=0) {
if(e < l or r < s) return;
if(s == e) { seg[i].v = (seg[i].v(s) > v(s))?seg[i].v:v; return; }
ll mid=(s+e)>>1;
if(l <= s && e <= r) {
Line A = seg[i].v, B = v; if(A(s) < B(s)) swap(A, B);
if(A(e) >= B(e)) seg[i].v = A;
else if(A(mid) >= B(mid)) {
seg[i].v = A;
if(seg[i].r == -1) seg[i].r = seg.size(), seg.pb(Node());
update(seg, B, mid+1, e, mid+1, e, seg[i].r);
}
else {
seg[i].v = B;
if(seg[i].l == -1) seg[i].l = seg.size(), seg.pb(Node());
update(seg, A, s, mid, s, mid, seg[i].l);
}
return;
}
if(seg[i].l == -1) seg[i].l = seg.size(), seg.pb(Node());
if(seg[i].r == -1) seg[i].r = seg.size(), seg.pb(Node());
update(seg, v, l, r, s, mid, seg[i].l);
update(seg, v, l, r, mid+1, e, seg[i].r);
}
// query max_{l_i <= x <= r_i} (a_i*x + b_i)
ll query(LiChao& seg, ll x, ll s=-L, ll e=L, ll i=0) {
if(i == -1 or x < s or e < x) return -inf;
if(s == e) return seg[i].v(x);
ll mid = (s+e)>>1;
return max({query(seg, x, s, mid, seg[i].l), query(seg, x, mid+1, e, seg[i].r), seg[i].v(x)});
}
// LiChao seg(1, Node());
// update(seg, {a, b}, l, r);
// ll v = query(seg, x);

37
source/DS/PBDS.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include <bits/stdc++.h>
#include <ext/rope>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace __gnu_cxx;
template<typename T>
using indexed_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
indexed_set<int> s;
s.insert(3); s.insert(2); s.insert(3); s.insert(9); s.insert(7); //2 3 7 9
s.insert(5); //2 3 5 7 9
s.erase(5); //2 3 7 9
auto x = s.find_by_order(2); // *x : 7
s.order_of_key(6) // 2
s.order_of_key(7) // 2
s.order_of_key(8) // 3
/////////////////////////////////////////////////////////////
// greater_equal <- ordered_multiset / greater <- ordered_multiset
#define oset_greater tree<ll, null_type, greater_equal<ll>, rb_tree_tag, tree_order_statistics_node_update>
#define oset_less tree<ll, null_type, less_equal<ll>, rb_tree_tag, tree_order_statistics_node_update>
void oset_m_erase(ordered_set_greater &OS, ll val){
int index = OS.order_of_key(val);
oset_greater::iterator it = OS.find_by_order(index);
if(it != OS.end() && *it == val) OS.erase(it);
}
/////////////////////////////////////////////////////////////
rope<ll> r;
r.insert(r.size() - t, i); //r.size()-t번째 자리에 i를 삽입
r.substr(a, b - a + 1) // a부터 (b-a+1)개 만큼을 잘라낸다. 즉, [a, b] 선택

86
source/DS/STBeats.cpp Normal file
View File

@@ -0,0 +1,86 @@
const int inf = 1e9+7;
#define data _data
struct data{
ll mx, mx_cnt, mx2, sum;
constexpr data(ll m):mx(m), mx_cnt(1), mx2(-inf), sum(m) {}
constexpr data(ll mx, ll mx_cnt, ll mx2, ll sum):mx(mx), mx_cnt(mx_cnt), mx2(mx2), sum(sum) {}
};
data join(data A, data B)
{
if(A.mx == B.mx)
return {A.mx, A.mx_cnt+B.mx_cnt, max(A.mx2, B.mx2), A.sum+B.sum};
if(A.mx < B.mx) swap(A, B);
return {A.mx, A.mx_cnt, max(A.mx2, B.mx), A.sum+B.sum};
}
using Seg = vector<data>;
void init(Seg& seg, int i, int s, int e, ll* A)
{
if(s == e) { seg[i] = A[s]; return; }
int mid = (s+e)/2;
init(seg, i*2, s, mid, A); init(seg, i*2+1, mid+1, e, A);
seg[i] = join(seg[i*2], seg[i*2+1]);
}
void prop(Seg& seg, int i, int s, int e)
{
if(s == e) return;
for(auto t : {i*2, i*2+1}) {
if(seg[t].mx > seg[i].mx) {
seg[t].sum -= seg[t].mx_cnt * (seg[t].mx - seg[i].mx);
seg[t].mx = seg[i].mx;
}
}
}
void update(Seg& seg, int i, int s, int e, int a, int b, ll v)
{
prop(seg, i, s, e);
if(e<a || b<s || seg[i].mx <= v) return;
if(a<=s && e<=b && seg[i].mx2 < v)
{
seg[i].sum -= seg[i].mx_cnt * (seg[i].mx - v);
seg[i].mx = v;
prop(seg, i, s, e);
return;
}
int mid = (s+e)/2;
update(seg, i*2, s, mid, a, b, v);
update(seg, i*2+1, mid+1, e, a, b, v);
seg[i] = join(seg[i*2], seg[i*2+1]);
}
ll querymax(Seg& seg, int i, int s, int e, int a, int b)
{
prop(seg, i, s, e);
if(e<a || b<s) return -inf;
if(a<=s && e<=b) return seg[i].mx;
int mid = (s+e)/2;
return max(querymax(seg, i*2, s, mid, a, b), querymax(seg, i*2+1, mid+1, e, a, b));
}
ll querysum(Seg& seg, int i, int s, int e, int a, int b)
{
prop(seg, i, s, e);
if(e<a || b<s) return 0;
if(a<=s && e<=b) return seg[i].sum;
int mid = (s+e)/2;
return querysum(seg, i*2, s, mid, a, b)+querysum(seg, i*2+1, mid+1, e, a, b);
}
const int N = 1e6+7;
ll A[N];
getint(n); get A;
Seg s(4*n, 0); init(s, 1, 1, n, A);
// A[i] = min(A[i], x) for l <= i <= r
update(s, 1, 1, n, l, r, x);
// summation query, max query
querysum(s, 1, 1, n, l, r), querymax(s, 1, 1, n, l, r);

36
source/DS/SegmentTree.cpp Normal file
View File

@@ -0,0 +1,36 @@
struct Data{
ll sum, lazy;
constexpr Data(ll m):sum(m), lazy(){}
constexpr Data(ll sum, ll lazy):sum(sum), lazy(lazy){}
};
Data join(Data A, Data B) {return A.sum+B.sum;}
using Seg = vector<Data>;
void init(Seg& seg, int i, int s, int e, ll *A) {
if(s == e) {seg[i] = A[s]; return;}
int mid = (s+e)>>1;
init(seg, i*2, s, mid, A); init(seg, i*2+1, mid+1, e, A);
seg[i] = join(seg[i*2], seg[i*2+1]);
}
void prop(Seg& seg, int i, int s, int e) {
seg[i].sum += seg[i].lazy * (e-s+1);
if(s != e) for(auto t:{i*2, i*2+1}) seg[t].lazy += seg[i].lazy;
seg[i].lazy = 0;
}
void update(Seg& seg, int i, int s, int e, int a, int b, ll v) {
prop(seg, i, s, e);
if(e<a||b<s) return;
if(a<=s&&e<=b) {seg[i].lazy+=v; prop(seg, i, s, e); return;}
int mid = (s+e)>>1;
update(seg, i*2, s, mid, a, b, v); update(seg, i*2+1, mid+1, e, a, b, v);
seg[i] = join(seg[i*2], seg[i*2+1]);
}
ll query(Seg& seg, int i, int s, int e, int a, int b) {
prop(seg, i, s, e);
if(e<a||b<s) return 0;
if(a<=s&&e<=b) return seg[i].sum;
int mid = (s+e)>>1;
return query(seg, i*2, s, mid, a, b) + query(seg, i*2+1, mid+1, e, a, b);
}

View File

@@ -0,0 +1,160 @@
namespace GMS
{
template<typename D, D (*join)(D,D), D _e>
class Segtree {
class Node {
Node *l, *r;
int s,e; D v;
public:
Node(int s, int e) :l(0), r(0), s(s), e(e), v(_e){};
~Node(){delete l; delete r;}
template<typename Dini>
friend void init(Node* node, Dini arr[] = NULL) {
int s = node->s, e=node->e, mid=(s+e)/2;
if(s == e) {
node->v = D(arr?arr[s]:_e);
return;
}
node->l = new Node(s, mid);
init(node->l, arr);
node->r = new Node(mid+1, e);
init(node->r, arr);
node->v = join(node->l->v, node->r->v);
}
friend D _query(Node* node, int a, int b) {
int s=node->s, e=node->e;
if(a <= s and e <= b) return node->v;
if(b < s or e < a) return _e;
return join(_query(node->l, a, b), _query(node->r, a, b));
}
friend void _update
(Node* node, int i, function<D(D)> upd) {
int s=node->s, e=node->e;
if(i < s or e < i) return;
if(s == e)
{
node->v = upd(node->v);
return;
}
_update(node->l, i, upd);
_update(node->r, i, upd);
node->v = join(node->l->v, node->r->v);
}
};
Node *root;
public:
template<typename Dini>
Segtree(int s,int e, Dini arr[] = NULL) {
root = new Node(s, e);
init(root, arr);
}
~Segtree(){delete root;}
D query(int s, int e)
{return _query(root, s, e);}
void update(int i, function<D(D)> upd)
{_update(root, i, upd);}
};
template<typename D, D (*join)(D,D), D _e, typename L, D (*apply)(D, L, int), L (*give)(L, L), L _l>
class LZSegtree {
class Node {
Node *l, *r;
int s,e;
D v; L lz;
void prop() {
v = apply(v, lz, e-s+1);
if(l) l->lz = give(l->lz, lz);
if(r) r->lz = give(r->lz, lz);
lz = _l;
}
public:
Node(int s, int e)
:l(0), r(0), s(s), e(e), v(_e), lz(_l){};
~Node(){delete l; delete r;}
template<typename Dini>
friend void init(Node* node, Dini arr[] = NULL) {
int s = node->s, e=node->e, mid=(s+e)/2;
if(s == e)
{
node->v = D(arr?arr[s]:_e);
return;
}
node->l = new Node(s, mid);
init(node->l, arr);
node->r = new Node(mid+1, e);
init(node->r, arr);
node->v = join(node->l->v, node->r->v);
}
friend D _query(Node* node, int a, int b) {
node->prop();
int s=node->s, e=node->e;
if(a <= s and e <= b) return node->v;
if(b < s or e < a) return _e;
return join(_query(node->l, a, b), _query(node->r, a, b));
}
friend void _update
(Node* node, int a, int b, function<L(L)> upd){
node->prop();
int s=node->s, e=node->e;
if(b < s or e < a) return;
if(a <= s and e <= b)
{
node->lz = upd(node->lz);
node->prop();
return;
}
_update(node->l, a, b, upd);
_update(node->r, a, b, upd);
node->v = join(node->l->v, node->r->v);
}
};
Node *root;
public:
template<typename Dini>
LZSegtree(int s,int e, Dini arr[] = NULL)
{
root = new Node(s, e);
init(root, arr);
}
~LZSegtree(){delete root;}
D query(int s, int e){return _query(root, s, e);}
void update(int s, int e, function<L(L)> upd){_update(root, s, e, upd);}
};
} // namespace GMS
//////////////////////////////////////////////////////
#define data _data
struct data {
int m, m_cnt;
constexpr data(int m):m(m), m_cnt(1){}
constexpr data(int m, int m_cnt):m(m), m_cnt(m_cnt){}
};
data join(data A, data B) {
if(A.m == B.m) return data(A.m, A.m_cnt+B.m_cnt);
if(A.m < B.m) return A;
else return B;
}
data apply(data A, int lz, int len)
{return {A.m+lz, A.m_cnt};}
int give(int a, int b){return a+b;}
using Seg = GMS::LZSegtree<data, join, {(int)1e9, 0}, int, apply, give, 0>;

127
source/DS/SplayTree.cpp Normal file
View File

@@ -0,0 +1,127 @@
struct Node
{
Node *p, *l, *r; int cnt; ll val;
ll m, M, sum; ll lazy; bool flip, dum;
Node(ll val, bool dum = false): p(0), l(0), r(0), cnt(1), val(val), m(val), M(val), sum(val), lazy(0), flip(0), dum(dum){}
void fix(){
cnt = 1+(l?l->cnt:0)+(r?r->cnt:0);
sum = val+(l?l->sum:0)+(r?r->sum:0);
m = min({val, (l?l->m:inf), (r?r->m:inf)});
M = max({val, (l?l->M:-1), (r?r->M:-1)});
}
void prop(){
if(flip){
swap(l, r); if(l) l->flip = !l->flip; if(r) r->flip = !r->flip; flip = false;
}
if(lazy){
val += lazy; sum += cnt * lazy; if(l) l->lazy += lazy; if(r) r->lazy += lazy; lazy = 0;
}
}
} *root;
// 자기보다 더 높은 노드를 루트로 하는 SplayTree를 조작하는 경우, 하위 SplayTree는 unvalid된다.
struct SplayTree{
Node *root = NULL, *rp = NULL;
SplayTree(){}
SplayTree(Node *rt){
if(!rt) return;
root = rt; rp = rt->p;
}
void mop(Node *node){
if(node == root) node->prop();
else mop(node->p);
if(node->l) node->l->prop();
if(node->r) node->r->prop();
}
void rotate(Node *node){
if(!root) return;
if(node->p == rp) return;
if(node->p->l == node){
Node *p = node->p, *g = p->p;
Node *a = node->l, *b = node->r, *c = p->r;
p->l = b; if(b) b->p = p;
p->r = c; if(c) c->p = p;
node->l = a; if(a) a->p = node;
node->r = p; p->p = node;
node->p = g; if(g) (g->l == p?g->l:g->r) = node;
p->fix(); node->fix();
if(p == root) root = node;
}
else{
Node *p = node->p, *g = p->p;
Node *a = p->l, *b = node->l, *c = node->r;
p->l = a; if(a) a->p = p;
p->r = b; if(b) b->p = p;
node->l = p; p->p = node;
node->r = c; if(c) c->p = node;
node->p = g; if(g) (g->l == p?g->l:g->r) = node;
p->fix(); node->fix();
if(p == root) root = node;
}
}
void splay(Node* node){
if(!root) return; assert(node); mop(node);
while(node->p != rp){
Node *p, *g;
p = node->p; g = p->p;
if(g == rp) rotate(node);
else if((p->l == node) == (g->l == p)) rotate(p), rotate(node);
else rotate(node), rotate(node);
}
root = node;
}
Node* insert(ll val, bool dum = false){
if(!root) return root = new Node(val, dum);
Node *now = root; while(now->r) now = now->r;
Node* ret = now->r = new Node(val, dum);
now->r->p = now; return splay(ret), ret;
}
Node* find_kth(int k) { // 0-indexed
assert(root); assert(root->cnt > k);
Node *now = root; now->prop();
while(true){
while(now->l and now->l->cnt > k) now = now->l, now->prop();
k -= now->l?now->l->cnt:0;
if(k == 0) break;
k--; now = now->r;
now->prop();
}
return splay(now), now;
}
// s-1, e+1번째 노드가 항상 존재해야 한다.
Node* gather(int s, int e){
find_kth(e+1);
SplayTree(root->l).find_kth(s-1);
assert(root->l->r); return root->l->r;
}
void update(int i, int j, ll val){
Node *node = gather(i, j); node->lazy += val;
node->prop(); node->p->fix(); node->p->p->fix();
}
void reverse(int i, int j){
Node *node = gather(i, j); node->flip = !node->flip;
}
void p_vals(){p_vals(root, 0, false);}
void p_vals(Node* node, ll lz, bool flip){
lz += node->lazy; flip ^= node->flip;
if(!flip){
if(node->l) p_vals(node->l, lz, flip);
if(!node->dum) printf("%lld ", node->val+lz);
if(node->r) p_vals(node->r, lz, flip);
}
else{
if(node->r) p_vals(node->r, lz, flip);
if(!node->dum) printf("%lld ", node->val+lz);
if(node->l) p_vals(node->l, lz, flip);
}
}
};
// SplayTree sp;
// fors(i, 0, n+1) arr[i] = sp.insert(i, i==0 or i == n+1);
// Node* node = sp.gather(l, r); sp.reverse(l, r);
// sp.find_kth(k); sp.splay(arr[k]);

60
source/DS/UF_QUndo.cpp Normal file
View File

@@ -0,0 +1,60 @@
struct dsu_pb {
const int N;
vi par; stack<pair<pii, pii> > s;
dsu_pb(int N):N(N), par(N) {
fors(i, 0, N-1) par[i] = -1;
}
int root(int i) {
if(par[i] < 0) return i;
return root(par[i]);
}
bool join(int i, int j) {
i = root(i); j = root(j);
s.push({{i, par[i]}, {j, par[j]}});
if(i == j) return false;
if(-par[i] < -par[j]) swap(i, j);
par[i] += par[j]; par[j] = i;
return true;
}
protected:
void unjoin() {
assert(!s.empty());
auto [i, j] = s.top(); s.pop();
par[i.fi] = i.se; par[j.fi] = j.se;
}
};
struct dsu_pf : public dsu_pb {
vector<pair<bool, pii> > st; // fi==0 -> B type, fi==1 -> A type
vector<pair<bool, pii> > tmp[2];
int A=0, B=0;
dsu_pf(int N):dsu_pb(N){}
bool join(int i, int j) {
st.pb({0, {i, j}}); B++;
return dsu_pb::join(i, j);
}
void pop_front() {
assert(!st.empty());
if(A == 0) {
forr(i, B) unjoin();
A = B; B = 0; reverse(all(st));
for(auto &[b, p]:st) b = 1, dsu_pb::join(p.fi, p.se);
}
else if(st.back().fi == false) {
tmp[st.back().fi].pb(st.back()); st.pop_back(); unjoin();
while(tmp[0].size() != tmp[1].size() and (unsigned) A != tmp[1].size()) {
tmp[st.back().fi].pb(st.back());
st.pop_back();
unjoin();
}
for(auto i:{0, 1}) reverse(all(tmp[i]));
for(auto i:{0, 1}) for(auto v:tmp[i])
st.pb(v), dsu_pb::join(v.se.fi, v.se.se);
tmp[0].clear(); tmp[1].clear();
}
A--; st.pop_back(); unjoin();
}
};

22
source/Fundemental.cpp Normal file
View File

@@ -0,0 +1,22 @@
#include <bits/stdc++.h>
#define getint(n) int n; scanf("%d%*c", &n)
#define getll(n) long long n; scanf("%lld%*c", &n)
#define getchar(n) char n; scanf("%c%*c", &n);
#define intab getint(a); getint(b)
#define forr(i, n) for(int i=1;i<=(n);i++)
#define fors(i, s, e) for(int i=(s); i<=(e); i++)
#define fore(i, e, s) for(int i=(e); i>=(s); i--)
#define fi first
#define se second
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pb push_back
using namespace std;
using ll = long long; using lll = __int128_t;
using pii = pair<int,int>; using pll = pair<ll,ll>;
using vi = vector<int>; using vl = vector<ll>;
using vii = vector<pii>; using vll = vector<pll>;

View File

@@ -0,0 +1,60 @@
struct ray
{
ll x, y, dx, dy; int i, j;
ray(pll A, pll B, int i = 0, int j = 0)
{
if(A.fi == B.fi && A.se > B.se) swap(A, B), swap(i, j);
if(A.fi>B.fi) swap(A, B), swap(i, j);
this->i = i; this->j = j;
x = A.fi; y = A.se;
dx = B.fi-A.fi; dy = B.se-A.se;
}
friend bool operator<(const ray& A, const ray& B)
{
return (A.dy*B.dx == B.dy*A.dx)?A.x == B.x?A.dx<B.dx:A.x<B.x:(A.dy*B.dx < B.dy*A.dx);
}
};
const int N = 1005;
vector<pair<pll, int> > p; vector<ray> vec;
int num[N];
void solve()
{
getint(n);
p.pb({{0, 0}, 0});
forr(i, n)
{
getll(a); getll(b); getchar(c);
p.pb({{a, b}, c=='R'});
}
sort(p.begin()+1, p.end());
forr(i, n) num[i] = i;
Seg s(1, n, p);
forr(i, n) fors(j, i+1, n) vec.pb(ray(p[i].fi, p[j].fi, i, j));
sort(all(vec));
ll ans = s.query(1, n).m;
for(auto r:vec)
{
int i = r.i, j = r.j;
assert(num[i]+1 == num[j]);
int ii = p[num[i]].se;
int jj = p[num[j]].se;
//printf("%d %d %d %d\n", i, j, ii, jj);
s.update(num[j], [ii](Dta A){return Dta(ii);});
//printf("%d\n", s.query(1, n).m);
s.update(num[i], [jj](Dta A){return Dta(jj);});
//printf("%d\n", s.query(1, n).m);
swap(p[num[i]], p[num[j]]);
swap(num[i], num[j]);
ans = max(ans, (ll)s.query(1, n).m);
}
printf("%lld\n", ans);
}

26
source/Geometry/Geo.cpp Normal file
View File

@@ -0,0 +1,26 @@
forr(i, now) vec.pb(A[i]);
sort(all(vec));
vll upper;
for(auto i:vec)
{
while(upper.size() >= 2 && ccw(upper[upper.size()-2], upper.back(), i) >= 0)
upper.pop_back();
upper.push_back(i);
}
reverse(all(vec));
vll lower;
for(auto i:vec)
{
while(lower.size() >= 2 && ccw(lower[lower.size()-2], lower.back(), i) >= 0)
lower.pop_back();
lower.push_back(i);
}
assert(upper.front() == lower.back() && lower.front() == upper.back());
upper.pop_back(); lower.pop_back();
vll hull;
hull.insert(hull.end(), all(upper));
hull.insert(hull.end(), all(lower));

50
source/Geometry/HPI.cpp Normal file
View File

@@ -0,0 +1,50 @@
using ld = long double;
using pdd = pair<ld, ld>;
using line = pair<pdd, pdd>; // half plane : left side of vector fi->se
const ld eps = 1e-9;
pdd operator*(const pdd& a, ld s) { return {a.fi * s, a.se * s}; }
inline bool equals(ld a, ld b) { return abs(a - b) < eps; }
bool line_intersect(line& a, line& b, pdd& v) {
ld det = (a.se - a.fi) / (b.se - b.fi);
if (equals(det, 0)) return 0;
ld t = ((b.fi - a.fi) / (b.se - b.fi)) / det;
v = a.fi + (a.se - a.fi) * t;
return 1;
}
bool bad(line& a, line& b, line& c) {
pdd v; if(!line_intersect(a, b, v)) return 0;
return (c.se - c.fi) / (v - c.fi) <= eps;
}
vector<pdd> HPI(vector<line>& lns) {
auto lsgn = [&](const line& a) {
if(a.fi.se == a.se.se) return a.fi.fi > a.se.fi;
return a.fi.se > a.se.se;
};
sort(lns.begin(), lns.end(), [&](const line& a, const line& b) {
if(lsgn(a) != lsgn(b)) return lsgn(a) < lsgn(b);
return (a.se - a.fi) / (b.se - b.fi) > 0;
});
deque<line> dq;
for(auto l : lns){
while(dq.size() >= 2 && bad(dq[dq.size()-2], dq.back(), l)) dq.pop_back();
while(dq.size() >= 2 && bad(dq[0], dq[1], l)) dq.pop_front();
if(dq.size() < 2 || !bad(dq.back(), l, dq[0])) dq.pb(l);
}
vector<pdd> res;
if(dq.size() >= 3) {
for(int i = 0; i < (int)dq.size(); i++) {
int j = (i + 1) % (int)dq.size();
pdd v;
if(!line_intersect(dq[i], dq[j], v)) continue;
res.push_back(v);
}
}
return res;
}

View File

@@ -0,0 +1,47 @@
using pii=pair<int,int>;
pii operator+(pii A, pii B){return {A.fi+B.fi, A.se+B.se};}
pii operator-(pii A, pii B){return {A.fi-B.fi, A.se-B.se};}
ll operator*(pii A, pii B){return (ll)A.fi*B.fi+(ll)A.se*B.se;} // inner product
ll operator/(pii A, pii B){return (ll)A.fi*B.se-(ll)A.se*B.fi;} // outer product
// 각도 정렬 (O = pii(0, 0))
sort(P+1, P+1+n, [](pii A, pii B) {
if(B == O) return false;
if(A == O) return true;
return (A<O)!=(B<O)?A>B:A/B<0;
});
// 선분 교차
// Segment : fi에서 시작하는 se 벡터
// fi + k * se, 0 <= k <= 1
using Segment = pair<pii, pii>;
int isJoin(const Segment& A, const Segment& B) {
if(B.se/A.se != 0) {
ll p = (A.fi-B.fi)/A.se;
ll q = B.se/A.se;
if(q<0) q = -q, p = -p;
if(p < 0 or p > q) return false;
p = (B.fi-A.fi)/B.se;
q = A.se/B.se;
if(q<0) q = -q, p = -p;
if(p < 0 or p > q) return false;
return true;
}
else {
if((A.fi-B.fi)/A.se != 0) return false;
ll p = A.fi*A.se, q = (A.fi+A.se)*A.se;
ll r = B.fi*A.se, s = (B.fi+B.se)*A.se;
if(p>q) swap(p, q); if(r>s) swap(r, s);
if(max(p, r) > min(q, s)) return false;
return true;
}
}

View File

@@ -0,0 +1,16 @@
auto isunder = [](pii upper[], int u, pii x, bool inv = false){ // inv==true : isover
int r = inv?-1:1;
int idx = lower_bound(upper+1, upper+1+u, x,
[&r](pii a, pii b){return r*a.fi<r*b.fi;}) - upper;
if(idx > u) return false;
if(idx == 1) {
if(r*x.fi < r*upper[1].fi) return false;
else {
int h = upper[1].se;
if(upper[2].fi == upper[1].fi) h = upper[2].se;
return r*x.se <= r*h;
}
}
return ccw(upper[idx-1], upper[idx], x) <= 0;
};

View File

@@ -0,0 +1,163 @@
typedef pair<ll, ll> pll;
#define _x first
#define _y second
pll operator-(const pll &a, const pll &b){
return {a._x - b._x, a._y - b._y};
}
ll cross(const pll &a, const pll &b){
return a._x * b._y - b._x * a._y;
}
ll dot(const pll &a, const pll &b){
return a._x * b._x + a._y * b._y;
}
int ccw(const pll &p1, const pll &p2, const pll &p3){
ll res = cross(p2 - p1, p3 - p1);
return (res != 0) * (res < 0 ? -1 : 1);
}
// dist of point - point
double dist(const pll &p1, const pll &p2){
return sqrt((p1._x - p2._x) * (p1._x - p2._x) + (p1._y - p2._y) * (p1._y - p2._y));
}
// dist of line - point
double dist(const pll &l1, const pll &l2, const pll &p){
ll area = abs(cross(l2 - l1, p - l1));
return area / dist(l1, l2);
}
// dist of seg - point
double segDist(P& s, P& e, P& p) {
if (s==e) return (p-s).dist();
auto d = (e-s).dist2(), t = min(d,max(.0,(p-s).dot(e-s)));
return ((p-s)*d-(e-s)*t).dist()/d;
}
P perp() const { return P(-y, x); } // rotates +90 degrees
int sgn(T x) { return (x > 0) - (x < 0); } // sign of x
// Returns where p is as seen from s towards e. 1/0/-1 <-> left/on line/right.
int sideOf(P s, P e, P p) { return sgn(s.cross(e, p)); }
// Returns a vector of either 0, 1, or 2 intersection points.
template<class P>
vector<P> circleLine(P c, double r, P a, P b) {
P ab = b - a, p = a + ab * (c-a).dot(ab) / ab.dist2();
double s = a.cross(b, c), h2 = r*r - s*s / ab.dist2();
if (h2 < 0) return {};
if (h2 == 0) return {p};
P h = ab.unit() * sqrt(h2);
return {p - h, p + h};
}
// Computes the pair of points at which two circles intersect.
typedef Point<double> P;
bool circleInter(P a,P b,double r1,double r2,pair<P, P>* out) {
if (a == b) { assert(r1 != r2); return false; }
P vec = b - a;
double d2 = vec.dist2(), sum = r1+r2, dif = r1-r2,
p = (d2 + r1*r1 - r2*r2)/(d2*2), h2 = r1*r1 - p*p*d2;
if (sum*sum < d2 || dif*dif > d2) return false;
P mid = a + vec*p, per = vec.perp() * sqrt(fmax(0, h2) / d2);
*out = {mid + per, mid - per};
return true;
}
// Returns true iff p lies on the line segment from s to e.
template<class P> bool onSegment(P s, P e, P p) {
return p.cross(s, e) == 0 && (s - p).dot(e - p) <= 0;
}
// Circumcircle
typedef Point<double> P;
double ccRadius(const P& A, const P& B, const P& C) {
return (B-A).dist()*(C-B).dist()*(A-C).dist()/
abs((B-A).cross(C-A))/2;
}
P ccCenter(const P& A, const P& B, const P& C) {
P b = C-A, c = B-A;
return A + (b*c.dist2()-c*b.dist2()).perp()/b.cross(c)/2;
}
// Minimum enclosing circle
pair<P, double> mec(vector<P> ps) {
shuffle(all(ps), mt19937(time(0)));
P o = ps[0];
double r = 0, EPS = 1 + 1e-8;
rep(i,0,sz(ps)) if ((o - ps[i]).dist() > r * EPS) {
o = ps[i], r = 0;
rep(j,0,i) if ((o - ps[j]).dist() > r * EPS) {
o = (ps[i] + ps[j]) / 2;
r = (o - ps[i]).dist();
rep(k,0,j) if ((o - ps[k]).dist() > r * EPS) {
o = ccCenter(ps[i], ps[j], ps[k]);
r = (o - ps[i]).dist();
}
}
}
return {o, r};
}
// point inside convex hull in logN
bool inHull(const vector<P>& l, P p, bool strict = true) {
int a = 1, b = sz(l) - 1, r = !strict;
if (sz(l) < 3) return r && onSegment(l[0], l.back(), p);
if (sideOf(l[0], l[a], l[b]) > 0) swap(a, b);
if (sideOf(l[0], l[a], p) >= r || sideOf(l[0], l[b], p)<= -r)
return false;
while (abs(a - b) > 1) {
int c = (a + b) / 2;
(sideOf(l[0], l[c], p) > 0 ? b : a) = c;
}
return sgn(l[a].cross(l[b], p)) < r;
}
// convex hull
vector<pll> convex_hull(vector<pii> &arr){
vector<pll> up, down;
for(auto p : arr){
while(up.size() >= 2 && ccw(up[up.size() - 2], up[up.size() - 1], p) >= 0) up.pop_back();
while(down.size() >= 2 && ccw(down[down.size() - 2], down[down.size() - 1], p) <= 0) down.pop_back();
up.push_back(p);
down.push_back(p);
}
up.insert(up.end(), down.rbegin() + 1, down.rend());
return up;
}
// rotating callipers
typedef Point<ll> P;
array<P, 2> hullDiameter(vector<P> S) {
int n = sz(S), j = n < 2 ? 0 : 1;
pair<ll, array<P, 2>> res({0, {S[0], S[0]}});
rep(i,0,j)
for (;; j = (j + 1) % n) {
res = max(res, {(S[i] - S[j]).dist2(), {S[i], S[j]}});
if ((S[(j + 1) % n] - S[j]).cross(S[i + 1] - S[i]) >= 0)
break;
}
return res.second;
}
// Closest pair
typedef Point<ll> P;
pair<P, P> closest(vector<P> v) {
assert(sz(v) > 1);
set<P> S;
sort(all(v), [](P a, P b) { return a.y < b.y; });
pair<ll, pair<P, P>> ret{LLONG_MAX, {P(), P()}};
int j = 0;
for (P p : v) {
P d{1 + (ll)sqrt(ret.first), 0};
while (v[j].y <= p.y - d.x) S.erase(v[j++]);
auto lo = S.lower_bound(p - d), hi = S.upper_bound(p + d);
for (; lo != hi; ++lo)
ret = min(ret, {(*lo - p).dist2(), {*lo, p}});
S.insert(p);
}
return ret.second;
}

View File

@@ -0,0 +1,109 @@
template <typename T>
class Point {
public:
T x, y;
Point() : x(0), y(0) {};
Point(T _x, T _y) : x(_x), y(_y) {};
Point operator+(Point p2){
return Point(x + p2.x, y + p2.y);
}
Point operator-(Point p2){
return Point(x - p2.x, y - p2.y);
}
T operator*(Point p2){
return x * p2.x + y * p2.y;
}
T operator/(Point p2) {
return x * p2.y - p2.x * y;
}
T operator==(Point p2) {
return (x == p2.x) && (y == p2.y);
}
T sqdist() {
return x*x + y*y;
}
bool operator<(Point p2) {
if(y == p2.y)
return x < p2.x;
return y < p2.y;
}
};
namespace geometry {
template <typename T>
ll ccw(Point<T> center, Point<T> p2, Point<T> p3) {
ll res = (p2 - center) / (p3 - center);
return (res > 0) - (res < 0);
}
template <typename T>
double theta(Point<T> center, Point<T> p2, Point<T> p3) {
return acos(p2 * p3 / sqrt(p2.sqdist() * p3.sqdist()));
}
template <typename T>
function<bool(Point<T> &, Point<T> &, Point<T>)> cmp_point = [](Point<T> &l, Point<T> &r, Point<T> O = {(T)0, (T)0}) -> bool {
return (l < O) != (r < O) ? l < r : l/r > 0;
};
template <typename T>
T sq_dist(Point<T> &p1, Point<T> &p2) {
return (p2.x - p1.x)*(p2.x - p1.x) + (p2.y - p1.y)*(p2.y - p1.y);
}
template <typename T>
double dist(Point<T> &p1, Point<T> &p2) {
return sqrt((double)sq_dist(p1, p2));
}
template <typename T>
double line_point_dist(pair<Point<T>, Point<T>> &l, Point<T> p)
{
Point<T> p1 = p - l.first, p2 = l.second - l.first;
return abs(p1 / p2)/(dist(l.first, l.second));
}
template <typename T>
double line_min_dist(pair<Point<T>, Point<T>> &l1, pair<Point<T>, Point<T>> &l2) {
double ans = INFINITY;
ans = min({ans, dist(l1.first, l2.first), dist(l1.first, l2.second), dist(l1.second, l2.first), dist(l1.second, l2.second)});
if((l1.second - l1.first)*(l2.first - l1.first) > 0 && (l1.first - l1.second)*(l2.first - l1.second) > 0)
ans = min({ans, line_point_dist<double>(l1, l2.first)});
if((l1.second - l1.first)*(l2.second - l1.first) > 0 && (l1.first - l1.second)*(l2.second - l1.second) > 0)
ans = min({ans, line_point_dist<double>(l1, l2.second)});
swap(l1, l2);
if((l1.second - l1.first)*(l2.first - l1.first) > 0 && (l1.first - l1.second)*(l2.first - l1.second) > 0)
ans = min({ans, line_point_dist<double>(l1, l2.first)});
if((l1.second - l1.first)*(l2.second - l1.first) > 0 && (l1.first - l1.second)*(l2.second - l1.second) > 0)
ans = min({ans, line_point_dist<double>(l1, l2.second)});
swap(l1, l2);
return ans;
}
template <typename T>
vector<T> convex_hull(vector<Point<T>> &pts) {
assert(pts.size() >= 2);
vector<Point<T>> res;
swap(pts[0], *min_element(pts.begin(), pts.end()));
sort(pts.begin()+1, pts.end(), [&pts](Point<T> &a, Point<T> &b){
ll cw = ccw(pts[0], a, b);
if(cw) return cw > 0;
return sq_dist(pts[0], a) < sq_dist(pts[0], b);
});
auto itr = pts.begin();
res.push_back(*(itr++)); res.push_back(*(itr++));
while(itr != pts.end())
{
while(res.size() >= 2 && ccw(res[res.size()-2], res[res.size()-1], *itr) <= 0)
res.pop_back();
res.push_back(*(itr++));
}
return res;
}
}
using namespace geometry;

5
source/Graph/2SAT.cpp Normal file
View File

@@ -0,0 +1,5 @@
ok = true; // 1<=i&&i<=n : $x$, n+1<=i&&i<=2*n : $!x$
forr(i, n) {
if (scn[i] == scn[i+n]) ok = false;
ans[i] = (scn[i] < scn[i+n]);
}

View File

@@ -0,0 +1,13 @@
vector<int> sideadj[N];
int selby[M];
int chk[M], c;
bool matching(int s) {
for(auto i : sideadj[s]) {
if(chk[i] == c) continue;
chk[i] = c;
if(selby[i] and !matching(selby[i])) continue;
selby[i] = s;
return true;
}
return false;
}

69
source/Graph/Dinic.cpp Normal file
View File

@@ -0,0 +1,69 @@
struct Edge {
int to, cap, now;
Edge* rev;
Edge(int to,int cap):to(to), cap(cap), now(0){}
int left(){return cap - now;}
void flow(int f){now += f; rev->now -= f;}
void reset(){now = 0;}
};
vector<Edge*> adj[N];
int lv[N]; bool chk[N];
bool bfs(int S, int T) {
queue<int> q;
q.push(S); lv[S] = 0; chk[S] = true;
while(!q.empty()) {
int s = q.front(); q.pop();
for(auto i : adj[s]) {
if(i->left() and !chk[i->to]) {
lv[i->to] = lv[s]+1; chk[i->to] = true;
q.push(i->to);
}
}
}
return chk[T];
}
Edge* hist[N]; int last[N];
bool dfs(int s, int T) {
if(s == T) return true;
for(int &j=last[s]; j < adj[s].size(); j++) {
int i = adj[s][j]->to;
if(adj[s][j]->left() == 0 or lv[i] != lv[s]+1) continue;
hist[i] = adj[s][j];
if(dfs(i, T)) return true;
}
return false;
}
ll flow(int S,int T) {
ll ans = 0;
while(bfs(S, T)) {
while(dfs(S, T)) {
int m = 2e9;
int now = T;
while(S != now) {
m = min(m, hist[now]->left());
now = hist[now]->rev->to;
}
now = T;
while(S != now)
hist[now]->flow(m), now = hist[now]->rev->to;
ans += m;
}
memset(last, 0, sizeof last);
memset(chk, 0, sizeof chk);
}
return ans;
}
// isDir : isDirected => 양방향 간선이면 false
void connect(int from, int to, int cap, bool isDir = true) {
Edge *fw, *bw;
fw = new Edge(to, cap);
bw = new Edge(from, !isDir ? cap : 0);
fw->rev = bw; bw->rev = fw;
adj[from].push_back(fw);
adj[to].push_back(bw);
}

View File

@@ -0,0 +1,51 @@
// https://ideone.com/aO6cH4
namespace dtree{ // by cki86201
vector<int> E[N], RE[N], rdom[N];
int S[N], RS[N], cs;
int par[N], val[N], sdom[N], rp[N], dom[N];
void clear(int n) { cs = 0;
for(int i=0;i<=n;i++) {
par[i] = val[i] = sdom[i] = rp[i] = dom[i] = S[i] = RS[i] = 0;
E[i].clear(); RE[i].clear(); rdom[i].clear();
}
}
void add_edge(int x, int y) { E[x].push_back(y); }
void Union(int x, int y) { par[x] = y; }
int Find(int x, int c = 0) {
if(par[x] == x) return c ? -1 : x;
int p = Find(par[x], 1);
if(p == -1) return c ? par[x] : val[x];
if(sdom[val[x]] > sdom[val[par[x]]]) val[x] = val[par[x]];
par[x] = p;
return c ? p : val[x];
}
void dfs(int x) {
RS[ S[x] = ++cs ] = x;
par[cs] = sdom[cs] = val[cs] = cs;
for(int e : E[x]) {
if(S[e] == 0) dfs(e), rp[S[e]] = S[x];
RE[S[e]].push_back(S[x]);
}
}
int solve(int s, int *up) { // Calculate idoms
dfs(s);
for(int i=cs;i;i--) {
for(int e : RE[i]) sdom[i] = min(sdom[i], sdom[Find(e)]);
if(i > 1) rdom[sdom[i]].push_back(i);
for(int e : rdom[i]) {
int p = Find(e);
if(sdom[p] == i) dom[e] = i;
else dom[e] = p;
}
if(i > 1) Union(i, rp[i]);
}
for(int i=2;i<=cs;i++) if(sdom[i] != dom[i]) dom[i] = dom[dom[i]];
for(int i=2;i<=cs;i++) up[RS[i]] = RS[dom[i]];
return cs;
}
} // namespace dtree
int par[N];
dtree::add_edge(a, b); // a -> b
int cnt = dtree::solve(s, par);
// cnt : s에서 도달할 수 있는 정점, par: dominator tree의 par

67
source/Graph/MCMF.cpp Normal file
View File

@@ -0,0 +1,67 @@
struct Edge {
int to, cap, now;
ll cost;
Edge* rev;
Edge(int to,int cap, ll cost)
:to(to), cap(cap), now(0), cost(cost){}
int left(){return cap - now;}
ll flow(int f)
{now += f; rev->now -= f; return cost * f;}
void reset(){now = 0;}
};
vector<Edge*> adj[N];
Edge* hist[N]; ll dist[N]; bool inQueue[N], chk[N];
bool spfa(int s, int t) {
memset(dist, 0, sizeof(dist));
memset(chk, 0, sizeof(chk)); chk[s] = true;
queue<int> q;
memset(inQueue, 0, sizeof(inQueue));
q.push(s); inQueue[s] = true;
while(!q.empty()) {
int now = q.front();
q.pop(); inQueue[now] = false;
for(auto e : adj[now]) {
int next = e->to;
if(e->left() > 0 and
(chk[next] == false
or dist[next] > dist[now] + e->cost)) {
chk[next] = true;
dist[next] = dist[now] + e->cost;
hist[next] = e;
if(!inQueue[next])
q.push(next), inQueue[next] = true;
}
}
}
return chk[t];
}
// cost가 들어가면 항상 단방향만 가능하다. (양방향 : 2번 connect)
void connect(int from, int to, int cap, ll cost) {
Edge *fw, *bw;
fw = new Edge(to, cap, cost);
bw = new Edge(from, 0, -cost);
fw->rev = bw; bw->rev = fw;
adj[from].push_back(fw);
adj[to].push_back(bw);
}
//maximum matching & minimum cost
pair<ll, ll> flow(int S,int T) {
ll ans = 0; ll cost = 0;
while(spfa(S, T)) {
int m = 2e9;
int now = T;
while(S != now) {
m = min(m, hist[now]->left());
now = hist[now]->rev->to;
}
now = T;
while(S != now) {
cost += hist[now]->flow(m);
now = hist[now]->rev->to;
}
ans += m;
}
return {ans, cost};
}

74
source/Graph/Matching.cpp Normal file
View File

@@ -0,0 +1,74 @@
// From https://github.com/koosaga/olympiad
// matching_short.cpp
const int MAXN = 2020 + 1;
// 1-based Vertex index
int vis[MAXN], par[MAXN], orig[MAXN], match[MAXN], aux[MAXN], t, N;
vector<int> conn[MAXN];
queue<int> Q;
void addEdge(int u, int v) { conn[u].push_back(v); conn[v].push_back(u); }
void init(int n) {
N = n; t = 0;
for(int i=0; i<=n; ++i) {
conn[i].clear();
match[i] = aux[i] = par[i] = 0;
}
}
void augment(int u, int v) {
int pv = v, nv;
do {
pv = par[v]; nv = match[pv];
match[v] = pv; match[pv] = v;
v = nv;
} while(u != pv);
}
int lca(int v, int w) {
++t;
while(true) {
if(v) {
if(aux[v] == t) return v; aux[v] = t;
v = orig[par[match[v]]];
}
swap(v, w);
}
}
void blossom(int v, int w, int a) {
while(orig[v] != a) {
par[v] = w; w = match[v];
if(vis[w] == 1) Q.push(w), vis[w] = 0;
orig[v] = orig[w] = a;
v = par[w];
}
}
bool bfs(int u) {
fill(vis+1, vis+1+N, -1); iota(orig + 1, orig + N + 1, 1);
Q = queue<int> (); Q.push(u); vis[u] = 0;
while(!Q.empty()) {
int v = Q.front(); Q.pop();
for(int x: conn[v]) {
if(vis[x] == -1) {
par[x] = v; vis[x] = 1;
if(!match[x]) return augment(u, x), true;
Q.push(match[x]); vis[match[x]] = 0;
}
else if(vis[x] == 0 && orig[v] != orig[x]) {
int a = lca(orig[v], orig[x]);
blossom(x, v, a); blossom(v, x, a);
}
}
}
return false;
}
int Match() {
int ans = 0;
// find random matching (not necessary, constant improvement)
vector<int> V(N-1); iota(V.begin(), V.end(), 1);
shuffle(V.begin(), V.end(), mt19937(0x94949));
for(auto x: V) if(!match[x]){
for(auto y: conn[x]) if(!match[y]) {
match[x] = y, match[y] = x;
++ans; break;
}
}
for(int i=1; i<=N; ++i) if(!match[i] && bfs(i)) ++ans;
return ans;
}

View File

@@ -0,0 +1,28 @@
vi adj[N];
int in[N], c = 0;
stack<int> p;
bool fin[N]; int scn[N], nscc = 0;
int dfs(int s) {
in[s] = ++c;
p.push(s);
int m = c;
for(auto i : adj[s]) {
if(in[i] == 0) m = min(m, dfs(i));
else if(!fin[i]) m = min(m, in[i]);
}
if(m == in[s]) {
nscc++;
while(p.top() != s)
{
int i = p.top(); p.pop();
scn[i] = nscc; fin[i] = true;
}
p.pop();
scn[s] = nscc; fin[s] = true;
}
return m;
}
forr(i, n) if(!fin[i]) dfs(i);

View File

@@ -0,0 +1,107 @@
// https://gist.github.com/koosaga/d4afc4434dbaa348d5bef0d60ac36aa4
vector<int> berlekamp_massey(vector<int> x){
vector<int> ls, cur; int lf, ld;
for(int i=0; i<x.size(); i++){
ll t = 0;
for(int j=0; j<cur.size(); j++)
t = (t + (ll)x[i-j-1] * cur[j]) % mod;
if((t - x[i]) % mod == 0) continue;
if(cur.empty()){
cur.resize(i+1);
lf = i; ld = (t - x[i]) % mod;
continue;
}
ll k = -(x[i] - t) * ipow(ld, mod - 2) % mod;
vector<int> c(i-lf-1); c.push_back(k);
for(auto &j : ls) c.push_back(-j * k % mod);
if(c.size() < cur.size()) c.resize(cur.size());
for(int j=0; j<cur.size(); j++) c[j] = (c[j] + cur[j]) % mod;
if(i-lf+(int)ls.size()>=(int)cur.size())
tie(ls, lf, ld) = make_tuple(cur, i, (t - x[i]) % mod);
cur = c;
}
for(auto &i : cur) i = (i % mod + mod) % mod;
return cur;
}
int get_nth(vector<int> rec, vector<int> dp, ll n){
int m = rec.size();
vector<int> s(m), t(m);
s[0] = 1;
if(m != 1) t[1] = 1;
else t[0] = rec[0];
auto mul = [&rec](vector<int> v, vector<int> w){
int m = v.size();
vector<int> t(2 * m);
for(int j=0; j<m; j++){
for(int k=0; k<m; k++){
t[j+k] += (ll)v[j] * w[k] % mod;
if(t[j+k] >= mod) t[j+k] -= mod;
}
}
for(int j=2*m-1; j>=m; j--){
for(int k=1; k<=m; k++){
t[j-k] += (ll)t[j] * rec[k-1] % mod;
if(t[j-k] >= mod) t[j-k] -= mod;
}
}
t.resize(m);
return t;
};
while(n){
if(n & 1) s = mul(s, t);
t = mul(t, t);
n >>= 1;
}
ll ret = 0;
for(int i=0; i<m; i++) ret += (ll)s[i] * dp[i] % mod;
return ret % mod;
}
// 1. calculate vi x: the first terms of recurrence;
// 2. calculate vi p: berlekamp_massey(x)
// 3. int get_nth(p, x, n) : nth term
struct elem{int x, y, v;}; // A_(x, y) <- v, 0-based. no duplicate please..
vector<int> get_min_poly(int n, vector<elem> M){
// smallest poly P such that A^i = sum_{j < i} {A^j \times P_j}
vector<int> rnd1, rnd2;
mt19937 rng(0x14004);
auto randint = [&rng](int lb, int ub){
return uniform_int_distribution<int>(lb, ub)(rng);
};
fors(i, 0, n-1) rnd1.push_back(randint(1, mod - 1));
fors(i, 0, n-1) rnd2.push_back(randint(1, mod - 1));
vector<int> gobs;
fors(i, 0, 2*n+1){
int tmp = 0;
fors(j, 0, n-1){
tmp += (ll)rnd2[j] * rnd1[j] % mod;
if(tmp >= mod) tmp -= mod;
}
gobs.push_back(tmp);
vector<int> nxt(n);
for(auto &i : M){
nxt[i.x] += (ll)i.v * rnd1[i.y] % mod;
if(nxt[i.x] >= mod) nxt[i.x] -= mod;
}
rnd1 = nxt;
}
auto sol = berlekamp_massey(gobs);
reverse(sol.begin(), sol.end());
return sol;
}
ll det(int n, vector<elem> M){
vector<int> rnd;
mt19937 rng(0x14004);
auto randint = [&rng](int lb, int ub){
return uniform_int_distribution<int>(lb, ub)(rng);
};
fors(i, 0, n-1) rnd.push_back(randint(1, mod - 1));
for(auto &i : M){
i.v = (ll)i.v * rnd[i.y] % mod;
}
auto sol = get_min_poly(n, M)[0];
if(n % 2 == 0) sol = mod - sol;
for(auto &i : rnd) sol = (ll)sol * ipow(i, mod - 2) % mod;
return sol;
}

View File

@@ -0,0 +1,56 @@
class Matrix {
private:
ll c, r, mod; vector<vector<ll>> arr;
ll power(ll x, ll y, ll p) {
if (y == 0) return 1;
ll v = power(x, y/2, p) % p;
v = (v * v) % p;
return (y%2 == 0)? v : (x * v) % p;
}
ll modInverse(ll a, ll p) { return power(a, p-2, p); }
public:
Matrix(int _n, int _m, ll p) : c(_n), r(_m), mod(p), arr(_n, vl(_m, 0)){}
void setI() { assert(c == r); for(int i=0; i<c; i++) arr[i][i] = 1; }
vl& operator[](ll i) { return arr[i]; }
void swaprow(ll i, ll j) { swap(arr[i], arr[j]); }
pair<bool, Matrix> Inverse() {
assert(c == r);
Matrix victim = *this, retm(c, c, mod); retm.setI();
for (int k = 0; k < c; k++) {
int t = k - 1; while (t + 1 < c && !victim[++t][k]);
if (t == c - 1 && !victim[t][k])
return {false, Matrix(0, 0, 0)};
victim.swaprow(k, t), retm.swaprow(k, t);
ll d = victim[k][k];
for (int j = 0; j < c; j++) {
victim[k][j] = (victim[k][j] * modInverse(d, mod))%mod;
retm[k][j] = (retm[k][j] * modInverse(d, mod))%mod;
}
for (int i = 0; i<c; i++) if (i != k) {
ll m = victim[i][k];
for (int j = 0; j < c; j++) {
if (j >= k) victim[i][j] = (victim[i][j] - victim[k][j] * m + mod*mod)%mod;
retm[i][j] = (retm[i][j] - retm[k][j] * m + mod*mod)%mod;
}
}
}
return {true, retm};
}
vector<double> GaussElimination() {
assert(c == r - 1);
vector<double> retv(c, 0.0);
for(ll i=0; i<c; i++) for(ll j=1+i; j<c; j++) {
double tmp = arr[j][i];
for(ll k=i; k<r; k++)
arr[j][k] = arr[j][k] - (tmp / arr[i][i]) * arr[i][k];
}
ll p = c, q = 0;
for (ll p = c - 1; p >= 0; p--) {
retv[p] = arr[p][c] / arr[p][p];
for (q = p - 1; q >= 0; q--)
arr[q][c] = arr[q][c] - arr[q][p] * retv[p];
}
return retv;
}
};

View File

@@ -0,0 +1,5 @@
vector<ll> basis;
void insert(ll x) {
for(auto i:basis) x = min(x, x ^ basis[i]);
if (x != 0) basis.push_back(x);
}

13
source/Math/CRT.cpp Normal file
View File

@@ -0,0 +1,13 @@
pll crt(pll p, pll q) {
if(p.fi > q.fi) swap(p, q);
auto [a, A] = p;
auto [b, B] = q;
ll g = gcd(A, B);
if((b-a)%g != 0) return {-1, -1};
ll i = A, j = B, k = b-a;
i/=g; j/=g; k/=g;
auto [x, y] = diophantos(i, j);
return {(ll)((a+(lll)A*k*x)%(A*B/g)), A*B/g};
}

View File

@@ -0,0 +1,12 @@
pll diophantos(ll a, ll b) {
assert(a>0 and b>=0);
if(b == 0) return {1, 0};
auto [y, x] = diophantos(b, a%b); y = y-(a/b)*x;
if(x < 0 or x >= b) {
ll t = x/b;
if(x%b < 0) t--;
x -= b*t; y += a*t;
}
return {x, y};
}

61
source/Math/FFTConv.cpp Normal file
View File

@@ -0,0 +1,61 @@
using cpx = complex<double>;
using vcpx = vector<cpx>;
void fft(vcpx &a, bool inv = false) {
int n = a.size(), j = 0; assert((n&-n) == n);
for(int i=1; i<n; i++) {
int bit = (n >> 1);
while(j >= bit) {
j -= bit; bit >>= 1;
}
j += bit; if(i < j) swap(a[i], a[j]);
}
vcpx roots(n/2);
prec c = 2 * pi * (inv ? -1 : 1);
for(int i=0; i<n/2; i++)
roots[i] = cpx(cosl(c * i / n), sinl(c * i / n));
for(int i=2, step = n/i; i<=n; i<<=1, step = n/i)
for(int j=0; j<n; j+=i) for(int k=0; k<i/2; k++) {
cpx u = a[j+k], v = a[j+k+i/2]*roots[step*k];
a[j+k] = u+v;
a[j+k+i/2] = u-v;
}
if(inv) for(int i=0; i<n; i++) a[i] /= n;
}
ll mod = 1e9+7;
vl conv(const vl& AA,const vl& BB) {
const ll G = 1<<15;
int n = AA.size()+BB.size()-1;
int m = 1; while(m < n) m<<=1;
int a = AA.size(), b = BB.size();
vcpx A(m), B(m), C(m), D(m);
fors(i, 0, a-1) A[i] = cpx(AA[i]/G, AA[i]%G);
fors(i, 0, b-1) B[i] = cpx(BB[i]/G, BB[i]%G);
fft(A); fft(B);
fors(i, 0, m-1) {
int j = i?m-i:0;
cpx A1 = (A[i]+conj(A[j]))*cpx(0.5, 0);
cpx A2 = (A[i]-conj(A[j]))*cpx(0, -0.5);
cpx B1 = (B[i]+conj(B[j]))*cpx(0.5, 0);
cpx B2 = (B[i]-conj(B[j]))*cpx(0, -0.5);
C[i] = A1*B1 + A2*B2*cpx(0, 1);
D[i] = A2*B1 + A1*B2*cpx(0, 1);
}
fft(C, true); fft(D, true);
vl ret(m); ll G1 = G%mod, G2 = (lll)G*G%mod;
fors(i, 0, m-1) {
ll p = ll(C[i].real()+0.5);
ll q = ll(D[i].real()+0.5) + ll(D[i].imag()+0.5);
ll r = ll(C[i].imag()+0.5);
p %= mod; q %= mod; r %= mod;
ret[i] = (((lll)p*G2)%mod+((lll)q*G1)%mod+r%mod)%mod;
}
ret.resize(n);
return ret;
}

7
source/Math/FloorSum.cpp Normal file
View File

@@ -0,0 +1,7 @@
ll floor_sum(ll a, ll b, ll c, ll n)
{
if(a == 0) return b/c*n;
if(a>=c or b>=c) return n*(n-1)/2 * (a/c) + n * (b/c) + floor_sum(a%c, b%c, c, n);
ll m = (a*(n-1)+b)/c;
return m*n - floor_sum(c, c-b+a-1, a, m);
}

12
source/Math/Harmonic.cpp Normal file
View File

@@ -0,0 +1,12 @@
ll harmonic(ll n) {
ll ans = 0;
for(ll i = 1; i <= n; i = n/(n/i)+ 1) {
//for j \in [i, n/(n/i)] : n/j == n/i
ans += n/i * (n/(n/i) - i + 1);
// \sum_{i=1}^n {f(n/i)}
// ans += f(n/i) * (n/(n/i) - i + 1)
}
return ans;
}

View File

@@ -0,0 +1,26 @@
ll pow(ll a, ll b, ll mod) {
ll ret = 1;
for(int st=0; (1LL<<st) <= b; st++) {
if((1LL<<st) & b) ret=(lll)ret*a%mod;
a=(lll)a*a%mod;
}
return ret;
}
bool miller(ll n, ll a) {
if(n == a) return true;
ll x = n-1;
if(pow(a, x, n) != 1) return false;
while(x%2==0) {
x/=2;
ll t = pow(a, x, n);
if(t!=1 and t!=n-1) return false;
if(t==n-1) return true;
}
return true;
}
bool is_p(ll n) {
if(n<=2) return n==2;
vi D = {2, 3, 5, 7, 11, 13, 17, 23, 29, 31, 37};
for(auto i:D) if(!miller(n, i)) return false;
return true;
}

81
source/Math/NTT.cpp Normal file
View File

@@ -0,0 +1,81 @@
namespace GMS {
template<ll mod>
ll pow(ll a, ll b) {
a %= mod;
ll ret = 1;
while(b != 0) {
if(b&1) ret = ret*a%mod;
a = a*a%mod; b>>=1;
}
return ret;
}
template<ll mod, ll w>
void ntt(vector<ll> &a, bool inv = false) {
static_assert(mod <= (ll)2e9, "mod should be less than 2e9");
int n = a.size(), j = 0;
assert((n & -n) == n && (mod-1)%n == 0);
for(int i=1; i<n; i++) {
int bit = (n >> 1);
while(j >= bit) {
j -= bit;
bit >>= 1;
}
j += bit;
if(i < j) swap(a[i], a[j]);
}
static vector<ll> root[30], iroot[30];
for(int st=1; (1<<st) <= n; st++) {
if(root[st].empty()) {
ll t = pow<mod>(w, (mod-1)/(1<<st));
root[st].pb(1);
for(int i=1; i<(1<<(st-1)); i++)
root[st].pb(root[st].back()*t%mod);
}
if(iroot[st].empty()) {
ll t = pow<mod>(w, (mod-1)/(1<<st));
t = pow<mod>(t, mod-2);
iroot[st].pb(1);
for(int i=1; i<(1<<(st-1)); i++)
iroot[st].pb(iroot[st].back()*t%mod);
}
}
vector<ll>* r = (inv?root:iroot);
for(int st = 1; (1<<st) <= n; st++) {
int i = 1<<st; //int step = n / i;
for(int j=0; j<n; j+=i) {
for(int k=0; k<i/2; k++) {
ll u = a[j+k], v = a[j+k+i/2] * r[st][k]%mod;
a[j+k] = (u+v)%mod;
a[j+k+i/2] = (mod+u-v)%mod;
}
}
}
if(inv) {
ll in = pow<mod>(n, mod-2);
for(int i=0; i<n; i++) a[i] = a[i]*in%mod;
}
}
template<ll mod, ll w>
vl conv(vl A, vl B) {
int n = A.size(), m = B.size();
int t = 1; while(t < n+m-1) t*=2;
A.resize(t); B.resize(t);
ntt<mod, w>(A); ntt<mod, w>(B);
fors(i, 0, t-1) A[i] = A[i]*B[i]%mod;
ntt<mod, w>(A, true);
A.resize(n+m-1);
return A;
}
} // namespace GMS

22
source/Math/PolladRho.cpp Normal file
View File

@@ -0,0 +1,22 @@
void fact(ll n, vl& ret) {
if(n == 1) return;
else if(n%2 == 0) ret.pb(2), fact(n/2, ret);
else if(is_p(n)) ret.pb(n);
else {
ll a, b, c, g = n;
auto f = [&c, &n](ll x)->ll{return (c+(lll)x*x)%n;};
do {
if(g == n) a=b=rand()%(n-2)+2, c=rand()%20+1;
a=f(a); b=f(f(b));
g = gcd(a-b, n);
} while(g == 1);
fact(g, ret); fact(n/g, ret);
}
}
vl po_rho(ll n) {
vl ret;
fact(n, ret);
sort(all(ret));
return ret;
}

149
source/Math/Polynomial.cpp Normal file
View File

@@ -0,0 +1,149 @@
namespace GMS {
template<ll mod, ll w>
struct Qring : public vl {
using poly = Qring<mod, w>;
Qring() : vl(1, 0) {}
Qring(ll c) : vl(1, c%mod) {}
Qring(ll c, int n) : vl(n, c%mod) {}
Qring(const vl& cp) : vl(cp) {for(auto &i:*this) i%=mod;}
ll& operator[](ll idx) {
if((unsigned)idx < size()) return vl::operator[](idx);
this->resize(idx+1); return vl::operator[](idx);
}
ll operator[](ll idx) const {
if((unsigned)idx < size()) return vl::operator[](idx);
return 0LL;
}
void adjust() { while(size() > 1 and back() == 0) pop_back(); }
void adjust(int n){resize(n, 0);}
ll operator()(ll x) {
x %= mod; ll ret = 0;
for(auto it=rbegin(); it!=rend(); it++)
ret = (ret*x+*it)%mod;
return ret;
}
friend poly operator%(const poly& A, int B){ // remainder by x^B
poly ret(A); ret.resize(B, 0);
return ret;
}
friend poly operator+(const poly& A, const poly& B) {
int n = max(A.size(), B.size()); poly ret(0, n);
fors(i, 0, n-1) ret[i] = A[i]+B[i];
for(auto&i:ret) if(i >= mod) i -= mod;
return ret.adjust(), ret;
}
friend poly operator-(const poly& A) {
int n = A.size(); poly ret(0, n);
fors(i, 0, n-1) ret[i] = A[i]?mod-A[i]:0;
return ret;
}
friend poly operator-(const poly& A, const poly& B) {
int n = max(A.size(), B.size());
poly ret(0, n);
fors(i, 0, n-1) ret[i] = (mod+A[i]-B[i])%mod;
return ret.adjust(), ret;
}
friend poly operator*(ll x, const poly& B) {
poly ret(B); x %= mod;
for(auto &i : ret) i = (i*x)%mod;
return ret.adjust(), ret;
}
friend poly operator*(const poly& A, const poly& B) {
poly ret = conv<mod, w>(A, B);
// ACL : poly ret = atcoder::convolution<mod>(A, B);
return ret.adjust(), ret;
}
friend poly inv(const poly& A, int t) { assert(A[0] != 0);
poly g = pow<mod>(A[0], mod-2); int st=1;
while(st < t){st*=2; g = (-A%st*g%st+2)*g%st;}
return g.adjust(t), g;
}
friend poly diff(const poly& A) {
int n = A.size(); poly ret(0, n-1);
fors(i, 0, n-2) ret[i] = (i+1)*A[i+1]%mod;
return ret;
}
friend poly inte(const poly& A) {
static vector<ll> inv(1, 1);
int n = A.size(); poly ret(0, n+1);
inv.resize(max((int)inv.size(), n+1));
forr(i, n) if(inv[i] == 0) inv[i] = pow<mod>(i, mod-2);
forr(i, n) ret[i] = inv[i]*A[i-1]%mod;
return ret;
}
friend poly log(const poly& A, int t) { assert(A[0] == 1);
return inte(diff(A) * inv(A, t)%t)%t;
}
friend poly exp(const poly& A, int t) { assert(A[0] == 0);
poly g = 1; int st = 1;
while(st < t) {st*=2; g = (A%st-log(g, st)+1)*g%st;}
return g.adjust(), g;
}
friend poly pow(const poly& A, ll b, ll t) {
poly ret(A); ret.adjust();
if(ret.size() == 1) {
ret[0] = pow<mod>(ret[0], b);
return ret.adjust(t), ret;
}
ll idx = 0; while(ret[idx] == 0) idx++;
if((__int128_t) idx * b >= t) return poly(0, t);
ll c = ret[idx]; ll ic = pow<mod>(ret[idx], mod-2); poly g;
int n = ret.size();
fors(i, idx, n-1) g[i-idx] = ret[i]*ic%mod;
g.resize(t-idx*b);
g = exp(b * log(g, t-idx*b), t-idx*b);
c = pow<mod>(c, b);
ret = poly(0, t); fors(i, idx*b, t-1) ret[i] = g[i-idx*b] * c % mod;
return ret;
}
//Only just Polynomial, not Qring
void rev() { reverse(begin(), end()); }
friend poly div_quot(poly F, poly G) {
F.adjust(); G.adjust();
ll df = F.size(), dg = G.size();
if(df < dg) return poly(0);
F.rev(); G.rev();
F = F%(df-dg+1)*inv(G, df-dg+1)%(df-dg+1); F.rev();
return F;
}
friend poly div_rem(poly F, poly G) {return F-G*div_quot(F, G);}
friend poly shift(const poly& F, ll c) {
ll n = F.size(); c %= mod;
poly A(0, n); ll fac = 1;
fors(i, 0, n-1) A[i] = F[i]*fac%mod, fac = fac*(i+1)%mod;
A.rev();
poly C(1, n); fors(i, 1, n-1) C[i] = C[i-1]*c%mod;
ll facc = fac = pow<mod>(fac, mod-2)*n%mod;
fore(i, n-1, 0) C[i] = C[i]*fac%mod, fac = fac*i%mod;
poly B = C*A; B.resize(n); B.rev();
fore(i, n-1, 0) B[i] = B[i]*facc%mod, facc = facc*i%mod;
return B;
}
friend void calcG(vector<poly>& G, int i, int l, int r, const vl& p) {
if(l == r){ll g = p[l]?mod-p[l]:0; G[i] = vl({g, 1}); return;}
int mid = (l+r)/2;
calcG(G, i*2, l, mid, p); calcG(G, i*2+1, mid+1, r, p);
G[i] = G[i*2]*G[i*2+1];
}
friend void eval(const vector<poly>& G, int i, int l, int r, poly&& F, vl& ret) {
if(l == r){ret[l] = F[0];return;}
int mid=(l+r)/2;
eval(G, i*2, l, mid, div_rem(F, G[i*2]), ret);
eval(G, i*2+1, mid+1, r, div_rem(F, G[i*2+1]), ret);
}
friend vl multipoint_eval(const poly& A, const vl& B) {
int m = B.size();
vector<poly> G(4*m); calcG(G, 1, 0, m-1, B);
vl ret(m, 0); eval(G, 1, 0, m-1, div_rem(A, G[1]), ret);
return ret;
}
};
} // namespace GMS

View File

@@ -0,0 +1,23 @@
ll primary_root(ll p) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<ll> distrib(1, p-1);
//distrib(gen);
vl g = po_rho(p-1);
while(true) {
ll c = distrib(gen);
bool ok = true; ll u = p-1;
ll b = 1;
for(auto i:g) {
if(i != b) u = p-1;
ll x = pow(c, u/i, p);
if(x == 1) ok = false;
u /= i; b = i;
}
if(ok) return c;
}
}

View File

@@ -0,0 +1,56 @@
vector<ll> euler(1000003, -1), primes;
//Generate primes and also calculate the euler number
void genprime() {
for(ll i = 2;i<=1000002;i++) {
if(euler[i]==-1) {
primes.push_back(i);
euler[i] = i-1;
for(ll j = 2*i; j<=1000002; j+=i) {
if(euler[j]==-1)euler[j] = j;
euler[j] = (euler[j]/i)*(i-1);
}
}
}
}
//Calculates x raised to the power of p % m
ll powll(ll x, ll p, ll m = 1ll<<62)
// Mod inverse
ll inverse(ll x, ll m)
//finds (n!)_p
ll ff(ll n, ll p, ll q)
{
ll x = 1, y = powll(p, q);
for(ll i = 2; i<=n;i++) if(i%p)
x = (x*i)%y;
return x%y;
}
//Generalized Lucas Theorem calculates nCm mod p^q
ll lucas_pow_comb(ll n, ll m, ll p, ll q) {
ll r = n-m, x = powll(p, q);
ll e0 = 0, eq = 0;
ll mul = (p==2&&q>=3)? 1: -1;
ll cr = r, cm = m, carry = 0, cnt = 0;
while(cr||cm||carry) {
cnt++;
int rr = cr%p, rm = cm%p;
if(rr + rm + carry >= p) {
e0++;
if(cnt>=q)eq++;
}
carry = (carry+rr+rm)/p;
cr/=p; cm/=p;
}
mul = powll(p, e0)*powll(mul, eq);
ll ret = (mul % x + x) % x;
ll temp = 1;
for(ll i = 0;;i++)//This is THE line that calculates the formula {
ret = ((ret*ff((n/temp)%x, p, q)%x)%x*(inverse(ff((m/temp)%x, p, q), x)%x*inverse(ff((r/temp)%x, p, q), x)%x)%x)%x;
if(temp>n/p && temp>m/p && temp>r/p)
break;
temp = temp*p;
}
return (ret%x+x)%x;
}

167
source/Math/math.tex Normal file
View File

@@ -0,0 +1,167 @@
% Written by Anders Sjoqvist and Ulf Lundstrom, 2009
% The main sources are: tinyKACTL, Beta and Wikipedia
\subsection{Equations}
\[ax^2+bx+c=0 \Rightarrow x = \frac{-b\pm\sqrt{b^2-4ac}}{2a}\]
The extremum is given by $x = -b/2a$.
\[\begin{aligned}ax+by=e\\cx+dy=f\end{aligned}
\Rightarrow
\begin{aligned}x=\dfrac{ed-bf}{ad-bc}\\y=\dfrac{af-ec}{ad-bc}\end{aligned}\]
In general, given an equation $Ax = b$, the solution to a variable $x_i$ is given by
\[x_i = \frac{\det A_i'}{\det A} \]
where $A_i'$ is $A$ with the $i$'th column replaced by $b$.
\subsection{Inequality}
For positive $a$, $b$, $c$, $d$ with $\frac{a}{b} < \frac{c}{d}$, $\frac{a}{b} < \frac{a+c}{b+d} < \frac{c}{d}$ hold.
Also, for positive $a$, $b$, $c$, $d$, $\min(\frac{a}{b}, \frac{c}{d}) \leqslant \frac{a+c}{b+d} \leqslant max(\frac{a}{b}, \frac{c}{d})$.
e.g., for two sets of disjoint vertices $A$, $B$ of $G$,
\begin{align*}
\min \left( \frac{E(G[A])}{V(G[A])}, \frac{E(G[B])}{V(G[B])} \right) & \leqslant
\frac{E(G[A\cup B])}{V(G[A\cup B])} = \frac{E(G[A]) + E(G[B])}{V(G[A]) + V(G[B])} \\&
\leqslant \max \left( \frac{E(G[A])}{V(G[A])}, \frac{E(G[B])}{V(G[B])} \right)
\end{align*}
(therefore, the average degree of the disjoint set is larger when we divide them.)
\subsection{Recurrences}
If $a_n = c_1 a_{n-1} + \dots + c_k a_{n-k}$, and $r_1, \dots, r_k$ are distinct roots of $x^k - c_1 x^{k-1} - \dots - c_k$, there are $d_1, \dots, d_k$ s.t.
\[a_n = d_1r_1^n + \dots + d_kr_k^n. \]
Non-distinct roots $r$ become polynomial factors, e.g. $a_n = (d_1n + d_2)r^n$.
% \subsection{Trigonometry}
% \begin{align*}
% \sin(v+w)&{}=\sin v\cos w+\cos v\sin w\\
% \cos(v+w)&{}=\cos v\cos w-\sin v\sin w\\
% \tan(v+w)&{}=\dfrac{\tan v+\tan w}{1-\tan v\tan w}\\
% \sin v+\sin w&{}=2\sin\dfrac{v+w}{2}\cos\dfrac{v-w}{2}\\
% \cos v+\cos w&{}=2\cos\dfrac{v+w}{2}\cos\dfrac{v-w}{2}\\
% (V+W)\tan(v-w)/2&{}=(V-W)\tan(v+w)/2
% \end{align*}
% where $V, W$ are lengths of sides opposite angles $v, w$.
% \begin{align*}
% a\cos x+b\sin x&=r\cos(x-\phi)\\
% a\sin x+b\cos x&=r\sin(x+\phi)
% \end{align*}
% where $r=\sqrt{a^2+b^2}, \phi=\operatorname{atan2}(b,a)$.
\subsection{Geometry}
\subsubsection{Triangles}
Side lengths: $a,b,c$
Semiperimeter: $p=\dfrac{a+b+c}{2}$
Area: $A=\sqrt{p(p-a)(p-b)(p-c)}$
Circumradius: $R=\dfrac{abc}{4A}$
Inradius: $r=\dfrac{A}{p}$
Length of the median (divides the triangle into two equal area triangles): $m_a=\tfrac{1}{2}\sqrt{2b^2+2c^2-a^2}$
Length of the bisector (divides angles into two): $s_a=\sqrt{bc\left[1-\left(\dfrac{a}{b+c}\right)^2\right]}$
Law of sines: $\dfrac{\sin\alpha}{a}=\dfrac{\sin\beta}{b}=\dfrac{\sin\gamma}{c}=\dfrac{1}{2R}$
Law of cosines: $a^2=b^2+c^2-2bc\cos\alpha$
Law of tangents: $\dfrac{a+b}{a-b}=\dfrac{\tan\dfrac{\alpha+\beta}{2}}{\tan\dfrac{\alpha-\beta}{2}}$
\subsubsection{Quadrilaterals}
With side lengths $a,b,c,d$, diagonals $e, f$, diagonals angle $\theta$, area $A$ and
magic flux $F=b^2+d^2-a^2-c^2$:
\[ 4A = 2ef \cdot \sin\theta = F\tan\theta = \sqrt{4e^2f^2-F^2} \]
For cyclic quadrilaterals the sum of opposite angles is $180^\circ$,
$ef = ac + bd$, and $A = \sqrt{(p-a)(p-b)(p-c)(p-d)}$.
% \subsubsection{Spherical coordinates}
% \begin{center}
% \includegraphics[width=25mm]{source/Math/sphericalCoordinates.pdf}
% \end{center}
% \[\begin{array}{cc}
% x = r\sin\theta\cos\phi & r = \sqrt{x^2+y^2+z^2}\\
% y = r\sin\theta\sin\phi & \theta = \textrm{acos}(z/\sqrt{x^2+y^2+z^2})\\
% z = r\cos\theta & \phi = \textrm{atan2}(y,x)
% \end{array}\]
\subsection{Derivatives/Integrals}
\begin{align*}
\dfrac{d}{dx}\arcsin x = \dfrac{1}{\sqrt{1-x^2}} &&& \dfrac{d}{dx}\arccos x = -\dfrac{1}{\sqrt{1-x^2}} \\
\dfrac{d}{dx}\tan x = 1+\tan^2 x &&& \dfrac{d}{dx}\arctan x = \dfrac{1}{1+x^2} \\
\int\tan ax = -\dfrac{\ln|\cos ax|}{a} &&& \int x\sin ax = \dfrac{\sin ax-ax \cos ax}{a^2} \\
\int e^{-x^2} = \frac{\sqrt \pi}{2} \text{erf}(x) &&& \int xe^{ax}dx = \frac{e^{ax}}{a^2}(ax-1)
\end{align*}
Integration by parts:
\[\int_a^bf(x)g(x)dx = [F(x)g(x)]_a^b-\int_a^bF(x)g'(x)dx\]
\subsection{Sums}
\[ c^a + c^{a+1} + \dots + c^{b} = \frac{c^{b+1} - c^a}{c-1}, c \neq 1 \]
\begin{align*}
1 + 2 + 3 + \dots + n &= \frac{n(n+1)}{2} \\
1^2 + 2^2 + 3^2 + \dots + n^2 &= \frac{n(2n+1)(n+1)}{6} \\
1^3 + 2^3 + 3^3 + \dots + n^3 &= \frac{n^2(n+1)^2}{4} \\
1^4 + 2^4 + 3^4 + \dots + n^4 &= \frac{n(n+1)(2n+1)(3n^2 + 3n - 1)}{30} \\
\end{align*}
\subsection{Series}
$$e^x = 1+x+\frac{x^2}{2!}+\frac{x^3}{3!}+\dots,\,(-\infty<x<\infty)$$
$$\ln(1+x) = x-\frac{x^2}{2}+\frac{x^3}{3}-\frac{x^4}{4}+\dots,\,(-1<x\leq1)$$
$$\sqrt{1+x} = 1+\frac{x}{2}-\frac{x^2}{8}+\frac{2x^3}{32}-\frac{5x^4}{128}+\dots,\,(-1\leq x\leq1)$$
$$\sin x = x-\frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+\dots,\,(-\infty<x<\infty)$$
$$\cos x = 1-\frac{x^2}{2!}+\frac{x^4}{4!}-\frac{x^6}{6!}+\dots,\,(-\infty<x<\infty)$$
\subsection{Probability theory}
Let $X$ be a discrete random variable with probability $p_X(x)$ of assuming the value $x$. It will then have an expected value (mean) $\mu=\mathbb{E}(X)=\sum_xxp_X(x)$ and variance $\sigma^2=V(X)=\mathbb{E}(X^2)-(\mathbb{E}(X))^2=\sum_x(x-\mathbb{E}(X))^2p_X(x)$ where $\sigma$ is the standard deviation. If $X$ is instead continuous it will have a probability density function $f_X(x)$ and the sums above will instead be integrals with $p_X(x)$ replaced by $f_X(x)$.
Expectation is linear:
\[\mathbb{E}(aX+bY) = a\mathbb{E}(X)+b\mathbb{E}(Y)\]
For independent $X$ and $Y$, \[V(aX+bY) = a^2V(X)+b^2V(Y).\]
\subsubsection{Binomial distribution}
The number of successes in $n$ independent yes/no experiments, each which yields success with probability $p$ is $\textrm{Bin}(n,p),\,n=1,2,\dots,\, 0\leq p\leq1$.
\[p(k)=\binom{n}{k}p^k(1-p)^{n-k}\]
\[\mu = np,\,\sigma^2=np(1-p)\]
$\textrm{Bin}(n,p)$ is approximately $\textrm{Po}(np)$ for small $p$.
\subsubsection{First success distribution}
The number of trials needed to get the first success in independent yes/no experiments, each which yields success with probability $p$ is $\textrm{Fs}(p),\,0\leq p\leq1$.
\[p(k)=p(1-p)^{k-1},\,k=1,2,\dots\]
\[\mu = \frac1p,\,\sigma^2=\frac{1-p}{p^2}\]
\subsubsection{Poisson distribution}
The number of events occurring in a fixed period of time $t$ if these events occur with a known average rate $\kappa$ and independently of the time since the last event is $\textrm{Po}(\lambda),\,\lambda=t\kappa$.
\[p(k)=e^{-\lambda}\frac{\lambda^k}{k!}, k=0,1,2,\dots\]
\[\mu=\lambda,\,\sigma^2=\lambda\]
% \subsubsection{Uniform distribution}
% If the probability density function is constant between $a$ and $b$ and 0 elsewhere it is $\textrm{U}(a,b),\,a<b$.
% \[f(x) = \left\{
% \begin{array}{cl}
% \frac{1}{b-a} & a<x<b\\
% 0 & \textrm{otherwise}
% \end{array}\right.\]
% \[\mu=\frac{a+b}{2},\,\sigma^2=\frac{(b-a)^2}{12}\]
\subsubsection{Exponential distribution}
The time between events in a Poisson process is $\textrm{Exp}(\lambda),\,\lambda>0$.
\[f(x) = \left\{
\begin{array}{cl}
\lambda e^{-\lambda x} & x\geq0\\
0 & x<0
\end{array}\right.\]
\[\mu=\frac{1}{\lambda},\,\sigma^2=\frac{1}{\lambda^2}\]
% \subsubsection{Normal distribution}
% Most real random values with mean $\mu$ and variance $\sigma^2$ are well described by $\mathcal{N}(\mu,\sigma^2),\,\sigma>0$.
% \[ f(x) = \frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{(x-\mu)^2}{2\sigma^2}} \]
% If $X_1 \sim \mathcal{N}(\mu_1,\sigma_1^2)$ and $X_2 \sim \mathcal{N}(\mu_2,\sigma_2^2)$ then
% \[ aX_1 + bX_2 + c \sim \mathcal{N}(\mu_1+\mu_2+c,a^2\sigma_1^2+b^2\sigma_2^2) \]

File diff suppressed because it is too large Load Diff

29
source/Misc/FastI.cpp Normal file
View File

@@ -0,0 +1,29 @@
#define getint(n) int n; read(n)
#define getll(n) ll n; read(n)
#define inta getint(a)
#define intab getint(a); getint(b)
char get() {
static char buf[100000], *S=buf, *T=buf;
if(S == T) {
S = buf; T = buf + fread(buf, 1, 100000, stdin);
if(S == T) return EOF;
}
return *S++;
}
void read(int& n) {
n = 0; char c; bool neg = false;
for(c = get(); c < '0'; c=get()) if(c=='-') neg = true;
for(;c>='0';c=get()) n = n*10+c-'0';
if(neg) n = -n;
}
void read(ll& n) {
n = 0; char c; bool neg = false;
for(c = get(); c < '0'; c=get()) if(c=='-') neg = true;
for(;c>='0';c=get()) n = n*10+c-'0';
if(neg) n = -n;
}
int read(char s[]) {
char c; int p = 0; while((c = get()) <= ' ');
s[p++] = c; while((c = get()) >= ' ') s[p++] = c;
s[p] = '\0'; return p;
}

7
source/Misc/NegDiv.cpp Normal file
View File

@@ -0,0 +1,7 @@
#define div _div
ll div(ll A, ll B)
{
ll q = A/B;
if(A<0) q-=(B>0)-(B<0);
return q;
}

View File

7
source/Misc/mt19937.cpp Normal file
View File

@@ -0,0 +1,7 @@
const long long rand_L = 1;
const long long rand_R = 10;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<int> dist(rand_L, rand_R);
auto gen = bind(dist, rng);
gen(); gen(); gen();

View File

@@ -0,0 +1,49 @@
struct Node {
int next[26]; int par, int fail; bool isfin = false;
Node(){fail = 0; fors(i, 0, 25) next[i] = -1;}
};
Node trie[N]; int c;
void insert(char s[], int i, int node) {
if(s[i] == '\0') {
trie[node].isfin = true; return;
}
if(trie[node].next[s[i]-'a'] == -1) {
trie[node].next[s[i]-'a'] = ++c;
trie[c].par = node;
}
insert(s, i+1, trie[node].next[s[i]-'a']);
}
void bfs() {
queue<pii> q; q.push({0, -1});
while(!q.empty()) {
auto [node, x] = q.front(); q.pop();
if(x != -1) {
int pf = trie[trie[node].par].fail;
while(pf != 0 and trie[pf].next[x] == -1) pf = trie[pf].fail;
if(trie[node].par != 0 and trie[pf].next[x] != -1)
{
trie[node].fail = trie[pf].next[x];
trie[node].isfin |= trie[trie[pf].next[x]].isfin;
}
else trie[node].fail = 0;
}
fors(i, 0, 25) {
if(trie[node].next[i] == -1) continue;
q.push({trie[node].next[s[i]-'a'], i});
}
}
}
// For char* s, insert(s+1, 0, 0);
// trie[0].fail = 0; bfs();
// find trie from s:
int now = 0, ok = false;
for(int i = 0; s[i]; i++) {
while(now != 0 and trie[now].next[s[i]-'a'] == -1) now = trie[now].fail;
if(trie[now].next[s[i]-'a'] != -1) {
now = trie[now].next[s[i]-'a'];
if(trie[now].isfin) ok = true;
}
}

38
source/String/Eertree.cpp Normal file
View File

@@ -0,0 +1,38 @@
struct Eertree {
int len[N], link[N], nxt[N][26], r[N];
long long cnt[N]; int sz, last, n;
char s[N];
Eertree() {
memset(nxt, 0, sizeof(nxt));
memset(cnt, 0, sizeof(cnt));
s[0] = -1;
n = 0; sz = 2; last = 1;
len[0] = -1; link[0] = 0;
len[1] = 0; link[1] = 0;
}
int get_link(int v) {
while (s[n-len[v]-1] != s[n]) v = link[v];
return v;
}
void insert(char c) {
s[++n] = c;
int cur = get_link(last);
if (!nxt[cur][c-'a']) {
int now = sz++;
r[now] = n;
len[now] = len[cur] + 2;
if (len[now] == 1) link[now] = 1;
else link[now] = nxt[get_link(link[cur])][c-'a'];
nxt[cur][c-'a'] = now;
}
last = nxt[cur][c-'a'];
cnt[last]++;
}
void propagate() { fore(i, sz-1, 2) cnt[link[i]] += cnt[i]; }
};
Eertree et; forr(i, n) et.insert(s[i]);
int m = et.sz; et.propagate();
fors(i, 2, m-1) ans = max(ans, et.cnt[i] * et.len[i]);
// node i : s[(et.r[i]-et.len[i]+1)~(et.r[i])]
// distinct count of pal : m-2; count of node i : et.cnt[i];

View File

@@ -0,0 +1,92 @@
const int N = 1e5+7;
char s[N];
int F[N], Z[N], M[N];
int sa[N]; int ord[N], tmp[N], cnt[N];
int lcp[N];
int main() {
scanf("%s", s+1);
int n = strlen(s+1);
// KMP - fail function {
F[1] = 0; int j = 0;
for(int i=2; i<=n;i++)
{
while(j > 0 and s[i] != s[j+1]) j = F[j];
F[i] = j+=(s[i] == s[j+1]);
}
}
//Z - Z array {
Z[1] = n; int j = 1, r = 0;
for(int i=2; i<=n; i++)
{
Z[i] = i<j+r?min(Z[i-j+1], j+r-i):0;
while(s[1+Z[i]] == s[i+Z[i]]) Z[i]++;
if(j+r < i+Z[i]) j = i, r = Z[i];
}
}
//Manacher - M array {
M[1] = 0; int j = 1, r = 0;
for(int i=2; i<=n; i++)
{
M[i] = i<j+r?min(M[2*j-i], j+r-i):0;
while(1 <= i-M[i]-1 && i+M[i]+1 <= n
&& s[i-M[i]-1] == s[i+M[i]+1]) M[i]++;
if(j+r < i+M[i]) j = i, r = M[i];
}
}
//Suffix Array - SA {
int t = 1; ord[n+1] = 0; tmp[0] = 0; sa[0] = 0;
auto cmp = [&t, &n](int i,int j) {
return ord[i] == ord[j]
?ord[min(i+t, n+1)]<ord[min(j+t, n+1)]
:ord[i]<ord[j];
};
forr(i, n) ord[i] = s[i], sa[i] = i;
sort(sa+1, sa+1+n, [](int i,int j){return ord[i]<ord[j];});
forr(i, n) tmp[sa[i]] = tmp[sa[i-1]] + (ord[sa[i-1]]<ord[sa[i]]);
swap(tmp, ord);
while(t < n) {
fors(i, 0, n) cnt[i] = 0;
forr(i, n) cnt[ord[min(i+t, n+1)]]++;
forr(i, n) cnt[i] += cnt[i-1];
fore(i, n, 1) tmp[cnt[ord[min(i+t, n+1)]]--] = i;
fors(i, 0, n) cnt[i] = 0;
forr(i, n) cnt[ord[i]]++;
forr(i, n) cnt[i] += cnt[i-1];
fore(i, n, 1) sa[cnt[ord[tmp[i]]]--] = tmp[i];
forr(i, n) tmp[sa[i]] = tmp[sa[i-1]] + cmp(sa[i-1], sa[i]);
swap(ord, tmp);
t<<=1;
if(ord[sa[n]] == n) break;
}
}
//LCP array {
int k = 0;
forr(i, n) if(ord[i] != 1) {
int j = sa[ord[i]-1];
while(s[i+k] == s[j+k]) k++;
lcp[ord[i]] = k;
if(k > 0) k--;
}
}
printf("\nF : "); forr(i, n) printf("%d ", F[i]);
printf("\nZ : "); forr(i, n) printf("%d ", Z[i]);
printf("\nM : "); forr(i, n) printf("%d ", M[i]);
printf("\nSA : "); forr(i, n) printf("%d ", sa[i]);
printf("\nLCP : x "); fors(i, 2, n) printf("%d ", lcp[i]);
printf("\n"); forr(i, n) printf("%s\n", s+sa[i]);
}

17
source/String/KMP.cpp Normal file
View File

@@ -0,0 +1,17 @@
int fail[N]; // N : s의 최대 길이
vi kmp(char obj[], char s[]) {
vi ret;
for(int i = 1, j = 0; s[i]; i++) {
fail[i] = 0;
while(j > 0 and s[i] != s[j]) j = fail[j-1];
if(s[i] == s[j]) fail[i] = ++j;
}
for(int i = 0, j = 0; obj[i]; i++) {
while(j > 0 and obj[i] != s[j]) j = fail[j-1];
if(obj[i] == s[j]) {
if(s[j+1]) j++;
else ret.push_back(i-j), j = fail[j];
}
}
return ret;
}

View File

@@ -0,0 +1,132 @@
/////////////////////////////////////////////////////////
string s; //변수 선언
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
string s = "Hwan"; //output : Hwan
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
string s1("Hwan"); //output ㄷ: Hwan
string s2(4, 'A'); //output : AAAA
string s3(s1, 0, s1.length() - 2); //output : HW
string s4(s1, 2, s1.length()); //output : an
string s5(s2); //output : AAAA
string s6("ABCDE", 3); //output : ABC
char c[] = "TEST Code!!";
string s7(c); //output : TEST Code!!
/////////////////////////////////////////////////////////
string s = "ABCDE123";
cout << s.at(2) << endl; //output : C (범위가 맞지 않으면 예외처리를 함)
cout << s[0] << endl; //output : A
cout << s.front() << endl; //output : A
cout << s.back() << endl; //output : 3
const char * c = s.c_str(); //배열로써 접근이 가능하며 '\0'에 접근이 가능하다.
cout << c << endl; //output : ABCDE123
cout << (c_arr == s) ? true : false; //output : 1(true)
cout << (&(c_arr[0]) == &(s[0])) ? true : false; //output : 1(true)
/////////////////////////////////////////////////////////
string s = "ABCDE123";
string::iterator iter = s.begin();
string r_s, cp;
for (; iter != s.end(); iter++) {
cout << *iter;
if (*iter == 'E')
break;
} //output : ABCDE
copy(s.rbegin(), s.rend(), back_inserter(r_s));
copy(s.begin(), s.end(), back_inserter(cp));
cout << r_s << endl; //output : 321EDCBA
cout << (s == r_s) ? true : false; //output : 0(false)
cout << (s == cp) ? true : false; //output : 1(true)
cout << (&(s[0]) == &(cp[0])) ? true : false; //output : 0(false)
/////////////////////////////////////////////////////////
string s = "ABCDE123"
s.insert(0, "TEST"); //output : TESTABCDE123
s.insert(s.begin() + s.find_first_of('D') + 1, ':'); // output : TESTABCD:123(문자만 가능)
////////// (compare) s = TESTABCD:123 /////////////
s.compare("TESTABCD:123"); //output : 0
s.compare("a"); //output : -1
s.compare("X"); //output : -1
s.compare("BBBBBBBBBBBBBBB"); //output : 1
s.compare("100000000000000000000000"); //output : 1
s.compare("VVVVV"); //output : -1
////////// (erase) s = TESTABCD:123 /////////////
s.erase(0, 4); //output : ABCD:123
s.erase(find(s.begin(), s.end(), 'D')); //output : ABC:123('D'만 지움)
s.erase(s.find(':')); //output : ABC(':'부터 뒤 문자까지 모두 지움)
////////// (push, pop) s = ABC /////////////
s.push_back('S'); //output : ABCS
s.pop_back(); //output : ABC
////////// (append) s = ABC /////////////
s.append("TEST"); //output : ABCTEST
s.append(1, '1'); //output : ABCTEST1
s.append("123456789", 3, 3); //output : ABCTEST1456
////////// (clear) s = ABCTEST1456 /////////////
const char c[] = "Hwan";
s.append(c); //output : ABCTEST1456Hwan
s += c; //output : ABCTEST1456HwanHwan(capacity() = 15 -> 31)
s.clear(); //s.size() = 0, s.capacity() = 31
////////// (replace) s = '' /////////////
s.append("ABCD123"); //output : ABCD123
s.replace(4, 2, "Hwan"); //output : ABCDHwan3
s.replace(s.find('H'), s.size() - s.find('H'), "WOW"); //output : ABCDWOW
////////// (substr) s = ABCDWOW /////////////
string temp = s.substr(4); //output : WOW;
temp = s.substr(3, 2); //output : DW;
temp = s.substr(s.size() - 3, 50); //output : WOW;
////////// (copy) s = ABCDWOW /////////////
char arr[5]{};
s.copy(arr, sizeof arr - 1); //output : ABCD (마지막 '\n' 포함)
////////// (resize) s = ABCDWOW /////////////
s.resize(100); //output : ABCDWOW, s.size() = 100, s.capacity() = 111
s.resize(4); //output : ABCD, s.size() = 4, s.capacity() = 15
////////// (swap) s = ABCD /////////////
string sw = "AAA";
s.swap(sw); //s = "AAA", sw = "ABCD"
/////////// c++ 20 ///////////////////
s = "hello Hwan";
s.starts_with("hello"); //output : true;
s.starts_with('h'); //output : true;
s.starts_with("Hwan"); //output : false;
s.starts_with('x'); //output : false;
s.ends_with("Hwan"); //output : true;
s.ends_with('n'); //output : true;
s.ends_with("hello"); //output : false;
s.ends_with('q'); //output : false;

View File

@@ -0,0 +1,13 @@
int A[N], par[N];
stack<int> st;
forr(i, n) {
int l = -1;
while(!st.empty() && A[st.top()] < A[i])
l = st.top(), st.pop();
if(l != -1) par[l] = i;
if(!st.empty()) par[i] = st.top();
st.push(i);
}
while(st.size() != 1) st.pop();
par[st.top()] = st.top();

30
source/Tree/Centroid.cpp Normal file
View File

@@ -0,0 +1,30 @@
vi adj[N]; bool cent[N];
int sz[N], par[N];
void getSz(int s){
sz[s] = 1;
for(auto i:adj[s]){
if(cent[i]) continue; if(par[s] == i) continue;
par[i] = s; getSz(i); par[i] = 0;
sz[s] += sz[i];
}
}
int getCent(int s, int n){
for(auto i:adj[s]) if(!cent[i]&&sz[i]<sz[s]&&sz[i]>n/2)
return getCent(i, n);
return s;
}
int cpar[N];
int getCentTree(int s){
getSz(s); int C = getCent(s, sz[s]);
cent[C] = true;
for(auto i:adj[C]){
if(cent[i]) continue;
int c = getCentTree(i);
cpar[c] = C;
}
return C;
}
int C = getCentTree(1); cpar[C] = -1;

40
source/Tree/HLD.cpp Normal file
View File

@@ -0,0 +1,40 @@
BOJ 1
1 i c: i번 c로 .
2 u v: u에서 v로 .
vi adj[N]; int par[N]; int sz[N]; int d[N];
void dfs1(int s) {
sz[s] = 1;
for(auto it=adj[s].begin(); it!=adj[s].end(); it++)
if(*it == par[s]) {adj[s].erase(it); break;}
for(auto &i : adj[s]) {
par[i] = s; d[i] = d[s] + 1;
dfs1(i); sz[s] += sz[i];
if(sz[i] > sz[adj[s][0]]) swap(adj[s][0], i);
}
}
int in[N], c; int top[N];
void dfs2(int s) {
in[s] = ++c;
for(auto i : adj[s]) {
if(i == adj[s].front()) top[i] = top[s];
else top[i] = i;
dfs2(i);
}
}
int query(int a,int b) {
int ans = 0;
while(top[a] != top[b]) {
if(d[top[a]] > d[top[b]]) swap(a, b);
ans = max(ans, query(root, in[top[b]], in[b]));
b = par[top[b]];
}
if(d[a] > d[b]) swap(a, b);
return max(ans, query(root, in[a]+1, in[b]));
}
// dfs1(1); dfs2(1);
// forr(i, n) arr[in[i]] = m[{par[i], i}]; init(root, arr);
// q == 1: update(root, in[a], c); // in[a]를 c로 대체
// q == 2: query(a, b);

0
source/empty.cpp Normal file
View File

3
source/poro.sh Normal file
View File

@@ -0,0 +1,3 @@
mkdir {A..M}
alias solve='g++ main.cpp -o solve_exefile -g -fsanitize=undefined,address -fno-omit-frame-pointer -Wall -Wextra && echo "Compile Done" && time ./solve_exefile'
alias fast='g++ main.cpp -o solve_exefile -O2 -Wall && echo "Compile Done" && time ./solve_exefile'

7
source/qwerty.cpp Normal file
View File

@@ -0,0 +1,7 @@
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#define endl '\n'
#define foreach(i, l, r) for(ll i=(l); i<=(r); i++)
#define forreach(i, l, r) for(ll i=l; i>=(r); i--)

114
teamnote.sty Normal file
View File

@@ -0,0 +1,114 @@
\ProvidesPackage{teamnote}
\usepackage[left=1cm,right=1cm,top=2cm,bottom=1cm,a4paper]{geometry}
\usepackage{fancyhdr}
\usepackage{lastpage}
\usepackage{minted}
\usepackage{color}
\usepackage{indentfirst}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{import}
\usepackage{caption}
\usepackage[table,xcdraw]{xcolor}
\usepackage[T1]{fontenc}
\usepackage{setspace}
\setstretch{1} % No line-spacing
\renewcommand{\@listI}{% No spacing on list
\leftmargin=25pt
\rightmargin=0pt
\labelsep=5pt
\labelwidth=20pt
\itemindent=0pt
\listparindent=0pt
\topsep=0pt plus 2pt minus 4pt
\partopsep=0pt plus 1pt minus 1pt
\parsep=0pt plus 1pt
\itemsep=\parsep}
\setlength{\columnseprule}{0.4pt}
\pagenumbering{arabic}
\setminted{breaklines=true, tabsize=2, breaksymbolleft=}
\usemintedstyle{perldoc}
\newcommand{\revised}{Should be \textcolor{red}{\textbf{revised}}.}
\newcommand{\tested}{Should be \textcolor{red}{\textbf{tested}}.}
\newcommand{\added}{Should be \textcolor{red}{\textbf{added}}.}
\newcommand{\WIP}{\textcolor{red}{\textbf{Working in progress.}}}
\newcommand{\schoolname}{Some University}
\newcommand{\teamname}{Some Teamname}
\newcommand{\authorname}{Some Members}
\newcommand{\contestname}{Some Contest}
\newcommand{\maketitlepage}{\maketitle
\tableofcontents
\thispagestyle{fancy}
}
\DeclareRobustCommand{\teamnote}[4]{
\renewcommand{\schoolname}{#1}
\renewcommand{\teamname}{#2}
\renewcommand{\authorname}{#3}
\renewcommand{\contestname}{#4}
}
\pagestyle{fancy}
% \lhead{\schoolname{} -- \teamname}
% \rhead{Page \thepage{} of
\rhead{\schoolname{} -- \teamname -- \contestname}
\lhead{Page \thepage{} of
\ifthenelse{\pageref{LastPage} < 26}{\pageref{LastPage}}{\textcolor{red}{\textbf{\pageref{LastPage}}}}}
\fancyfoot{}
\title{Team Note of \teamname}
\author{\authorname}
\date{Compiled on \today}
\newboolean{BangShowUsage}
\setboolean{BangShowUsage}{false}
\newcommand{\ShowUsage}{\setboolean{BangShowUsage}{false}}
\newcommand{\HideUsage}{\setboolean{BangShowUsage}{true}}
\newboolean{BangShowComplexity}
\setboolean{BangShowComplexity}{false}
\newcommand{\ShowComplexity}{\setboolean{BangShowComplexity}{false}}
\newcommand{\HideComplexity}{\setboolean{BangShowComplexity}{true}}
\newboolean{BangShowAuthor}
\setboolean{BangShowAuthor}{false}
\newcommand{\ShowAuthor}{\setboolean{BangShowAuthor}{false}}
\newcommand{\HideAuthor}{\setboolean{BangShowAuthor}{true}}
\newcommand{\Algorithm}[6]{
\subsection{#1}
\ifthenelse{\equal{#2}{} \OR \boolean{BangShowUsage}}{}{\textbf{Usage:} #2}
\ifthenelse{\equal{#3}{} \OR \boolean{BangShowComplexity}}{}{\textbf{Time Complexity:} #3}
\ifthenelse{\equal{#6}{} \OR \boolean{BangShowAuthor}}{}{\textbf{Author:} #6}
\ifthenelse{\equal{#5}{}}{}{\ifthenelse{\equal{#4}{}}{\inputminted[]{cpp}{#5}}{\inputminted[]{#4}{#5}}}
}
\newcommand{\SubAlgorithm}[6]{
\subsubsection{#1}
\ifthenelse{\equal{#2}{} \OR \boolean{BangShowUsage}}{}{\textbf{Usage:} #2}
\ifthenelse{\equal{#3}{} \OR \boolean{BangShowComplexity}}{}{\textbf{Time Complexity:} #3}
\ifthenelse{\equal{#6}{} \OR \boolean{BangShowAuthor}}{}{\textbf{Author:} #6}
\ifthenelse{\equal{#5}{}}{}{\ifthenelse{\equal{#4}{}}{\inputminted[]{cpp}{#5}}{\inputminted[]{#4}{#5}}}
}