文章目录
1矩阵
1.1矩阵乘法
upd.2019.10.24 重载了[]
下标。
void add(int &x, int y){if ((x += y) >= mod) x -= mod;}
int mul(int x, int y){return 1ll*x*y%mod;}
struct MAT{
int n, m, a[N][N];
MAT(){}
MAT(int _n, int _m, bool b){
n = _n;
m = _m;
memset(a, 0, sizeof(a));
if (b)
for (int i = 1; i <= n; ++ i)
a[i][i] = 1;
}
int* operator [] (const int &x){
return a[x];
}
MAT operator * (MAT u){
if (m != u.n) return MAT(0, 0, 0);
MAT ret(n, u.m, 0);
for (int k = 1; k <= m; ++ k)
for (int i = 1; i <= n; ++ i)
for (int j = 1; j <= u.m; ++ j)
add(ret.a[i][j], mul(a[i][k], u.a[k][j]));
return ret;
}
MAT operator ^ (LL p){
if (n != m) return MAT(0, 0, 0);
MAT ret(n, m, 1), x = *this;
while (p){
if (p&1) ret = ret*x;
x = x*x;
p >>= 1;
}
return ret;
}
void print(){
for (int i = 1; i <= n; ++ i){
for (int j = 1; j <= m; ++ j)
printf("%d ", a[i][j]);
puts("");
}
}
};
1.2高斯消元
upd.2019.7.26
返回-1
→
\to
→无解
返回0
→
\to
→无数解
返回1
→
\to
→有实数解
const int N = ;
const double inf = , eps = ;
int gauss(double a[N][N], double x[N], int n)
{
for (int i = 1, nowr = 1; i <= n; ++ i, ++ nowr){
int now = nowr;
for (int j = nowr + 1; j <= n; ++ j)
if (fabs(a[j][i]) > fabs(a[now][i]))
now = j;
if (fabs(a[now][i]) < eps){-- nowr; continue;}
if (now != nowr)
for (int j = i; j <= n + 1; ++ j)
swap(a[nowr][j], a[now][j]);
for (int j = nowr + 1; j <= n; ++ j){
double k = a[j][i] / a[nowr][i];
for (int o = i; o <= n + 1; ++ o)
a[j][o] -= k * a[nowr][o];
}
}
for (int i = 1; i <= n; ++ i) x[i] = inf;
for (int i = n; i >= 1; -- i){
for (int j = i + 1; j <= n; ++ j)
if (x[j] != inf)
a[i][n + 1] -= a[i][j] * x[j];
bool flag = 1;
for (int j = 1; j <= n; ++ j)
if (fabs(a[i][j]) > eps)
flag = 0;
if (flag && fabs(a[i][n + 1]) > eps) return -1;
if (fabs(a[i][i]) > eps) x[i] = a[i][n + 1] / a[i][i];
}
for (int i = 1; i <= n; ++ i)
if (x[i] == inf)
return 0;
return 1;
}
1.3矩阵的行列式
对任意数取模化成上三角矩阵
int gauss(int a[N][N], int n, int p)
{
int ans = 1;
for (int i = 1; i <= n; ++ i){
for (int j = i + 1; j <= n; ++ j)
while (a[j][i]){
int k = a[i][i] / a[j][i];
for (int o = i; o <= n; ++ o)
a[i][o] = (a[i][o] - 1LL * a[j][o] * k % p + p) % p;
swap(a[j], a[i]);
ans = (p - ans) % p;
}
ans = 1LL * ans * a[i][i] % p;
}
return ans;
}
2图
2.1.1有边权
const int N = ;
const int M = ;
namespace Graph
{
int h[N], ecnt, nxt[M], v[M], w[M];
void clear(){ecnt = 1;}
void add_dir(int _u, int _v, int _w){
v[++ecnt] = _v; w[ecnt] = _w;
nxt[ecnt] = h[_u]; h[_u] = ecnt;
}
void add_undir(int _u, int _v, int _w){
add_dir(_u, _v, _w);
add_dir(_v, _u, _w);
}
}
using namespace Graph;
2.1.2没边权
const int N = ;
const int M = ;
namespace Graph
{
int h[N], ecnt, nxt[M], v[M];
void clear(){ecnt = 1;}
void add_dir(int _u, int _v){
v[++ecnt] = _v;
nxt[ecnt] = h[_u]; h[_u] = ecnt;
}
void add_undir(int _u, int _v){
add_dir(_u, _v);
add_dir(_v, _u);
}
}
using namespace Graph;
2.2.1有边权(结构体)
const int N = ;
const int M = ;
struct G
{
int h[N], ecnt, nxt[M], v[M], w[M];
void clear(){
ecnt = 1;
memset(h, 0, sizeof(h));
}
void add_dir(int _u, int _v, int _w){
v[++ecnt] = _v; w[ecnt] = _w;
nxt[ecnt] = h[_u]; h[_u] = ecnt;
}
void add_undir(int _u, int _v, int _w){
add_dir(_u, _v, _w);
add_dir(_v, _u, _w);
}
};
2.1.2没边权(结构体)
const int N = ;
const int M = ;
struct G
{
int h[N], ecnt, nxt[M], v[M];
void clear(){
ecnt = 1;
memset(h, 0, sizeof(h));
}
void add_dir(int _u, int _v){
v[++ecnt] = _v;
nxt[ecnt] = h[_u]; h[_u] = ecnt;
}
void add_undir(int _u, int _v){
add_dir(_u, _v);
add_dir(_v, _u);
}
};
3快读快输
3.0 输入输出
upd. 2019.11.5
template<class T>inline void read(T &x){
x = 0; bool fl = 0; char c = getchar();
while (!isdigit(c)){if (c == '-') fl = 1; c = getchar();}
while (isdigit(c)){x = (x<<3)+(x<<1)+c-'0'; c = getchar();}
if (fl) x = -x;
}
template<class T>inline void wr(T x){
if (x < 0) x = -x, putchar('-');
if (x > 9) wr(x / 10);
putchar(x % 10 + '0');
}
template<class T>inline void wrl(T x){
wr(x); puts("");
}
3.1 快读ver1.0
#define rdi read<int>
#define rdl read<long long>
template<typename T> inline T read(){
T x = 0; bool fl = 0;
char c = getchar();
while (!isdigit(c)){if (c == '-') fl = 1; c = getchar();}
while (isdigit(c)) x = (x<<3)+(x<<1)+c-'0', c = getchar();
return fl ? -x : x;
}
3.2 快读ver2.0
upd.2019.10.21
template<class T>inline void read(T &x){
x = 0; bool fl = 0; char c = getchar();
while (!isdigit(c)){if (c == '-') fl = 1; c = getchar();}
while (isdigit(c)){x = (x<<3)+(x<<1)+c-'0'; c = getchar();}
if (fl) x = -x;
}
3.3 快速输出
upd.2019.11.5
template<class T>inline void wr(T x){
if (x < 0) x = -x, putchar('-');
if (x > 9) wr(x / 10);
putchar(x % 10 + '0');
}
template<class T>inline void wrl(T x){
wr(x); puts("");
}
4树状数组
4.1区间求和
struct FEN_TR_SUM{
int t[N];
void clear(){
memset(t, 0, sizeof(t));
}
int lowbit(int x){return x&(-x);}
void add(int x, int y){
for (int i = x; i < N; i += lowbit(i))
t[i] += y;
}
int qry(int x){
if (x == 0) return 0;
int ret = 0;
for (int i = x; i > 0; i -= lowbit(i))
ret += t[i];
return ret;
}
};
4.2区间最值(max)
struct FEN_TR_MAX{
int t[N], a[N];
void clear(){
memset(a, 0, sizeof(a));
memset(t, 0, sizeof(t));
}
int lowbit(int x){return x&(-x);}
void upd(int x, int y, bool fl){ // fl:1新值覆盖原值,0取新旧值的较大值
if (y == a[x]) return;
if (y > a[x]){
a[x] = y;
for (int i = x; i < N; i += lowbit(i))
t[i] = max(t[i], y);
}
else{
if (!fl) return;
a[x] = y;
for (int i = x; i < N; i += lowbit(i)){
t[i] = a[i];
for (int j = i; j > 0; j -= lowbit(j))
t[i] = max(t[i], t[j]);
}
}
}
int qry(int x){ // 前缀最大值
int ret = 0;
for (int i = x; i > 0; i -= lowbit(i))
ret = max(ret, t[i]);
return ret;
}
int qry(int x, int y){ // 区间最大值
int ret = 0;
for (int i = y; i >= x; ){
int ni = i-lowbit(i);
if (ni+1 >= y) ret = max(ret, t[i]), i = ni;
else ret = max(ret, a[i]), -- i;
}
return ret;
}
void del(int x){
a[x] = 0;
for (int i = x; i < N; i += lowbit(i))
t[i] = 0;
}
};
5平衡树
5.1无旋Treap
upd. 2019.7.13
const int inf = ;
const int N = ;
namespace TREAP
{
int bin[N], bcnt, cnt;
int ch[N][2], fa[N], siz[N], v[N], r[N], root;
int new_cnt(){
if (bcnt) return bin[bcnt--];
return ++cnt;
}
void recyc(int x){
bin[++bcnt] = x;
}
int new_node(int _v){
int u = new_cnt();
ch[u][0] = ch[u][1] = fa[u] = 0; siz[u] = 1;
v[u] = _v; r[u] = random();
return u;
}
void push_up(int u){
siz[u] = siz[ch[u][0]]+siz[ch[u][1]]+1;
}
void reset(){
srand((unsigned)time(0));
bcnt = 0; cnt = -1; root = new_node(0); siz[0] = 0;
}
void split_rnk(int u, int &rtx, int &rty, int K){
if (!u) return (void)(rtx = rty = 0);
if (siz[ch[u][0]]+1 <= K) rtx = u, split_rnk(ch[u][1], ch[u][1], rty, K-siz[ch[u][0]]-1);
else rty = u, split_rnk(ch[u][0], rtx, ch[u][0], K);
push_up(u);
}
void split_val(int u, int &rtx, int &rty, int K){
if (!u) return (void)(rtx = rty = 0);
if (v[u] <= K) rtx = u, split_val(ch[u][1], ch[u][1], rty, K);
else rty = u, split_val(ch[u][0], rtx, ch[u][0], K);
push_up(u);
}
int merge(int x, int y){
if (!x || !y) return x|y;
if (r[x] < r[y]) return ch[x][1] = merge(ch[x][1], y), push_up(x), x;
else return ch[y][0] = merge(x, ch[y][0]), push_up(y), y;
}
}
using namespace TREAP;
5.2 Splay
upd. 2019.10.12
const int inf = ;
const int N = ;
namespace SPLAY
{
struct Node{
int ch[2], fa, siz, val, laz;
Node(){}
Node(int _fa, int _v){
ch[0] = ch[1] = laz = 0; siz = 1;
fa = _fa; val = _v;
}
}nd[N];
int root, cnt;
#define ls nd[u].ch[0]
#define rs nd[u].ch[1]
void push_up(int u){
nd[u].siz = nd[ls].siz+nd[rs].siz+1;
// add whatever you like
}
void push_down(int u){
if (nd[u].laz != 0){
// add whatever you like
nd[u].laz = 0;
}
}
void reset(int le_bd, int ri_bd){
nd[0] = Node(0, 0); nd[0].siz = 0;
nd[1] = Node(0, le_bd); nd[1].ch[1] = 2;
nd[2] = Node(1, ri_bd);
push_up(1);
root = 1; cnt = 2;
}
int son(int u){
return nd[nd[u].fa].ch[1] == u;
}
void rotate(int u){
int v = nd[u].fa, w = nd[v].fa;
int vs = son(u), ws = son(v);
nd[w].ch[ws] = u;
nd[v].fa = u;
nd[v].ch[vs] = nd[u].ch[vs^1];
nd[nd[u].ch[vs^1]].fa = v;
nd[u].fa = w;
nd[u].ch[vs^1] = v;
push_up(v); push_up(u);
}
void splay(int u, int goal){
while (nd[u].fa != goal){
if (nd[nd[u].fa].fa != goal) rotate(son(u) == son(nd[u].fa) ? nd[u].fa : u);
rotate(u);
}
if (goal == 0) root = u;
}
#undef ls
#undef rs
}
using namespace SPLAY;
6可持久化
6.1.1可持久化线段树(主席树)(结构体)
struct ZHUXI_TR{
struct NODE{
int ls, rs, val;
NODE(){}
NODE(int _x, int _y, int _z){
ls = _x; rs = _y; val = _z;
}
}nd[N*E];
int root[N], cnt;
int new_node(){
nd[++ cnt] = NODE(0, 0, 0);
return cnt;
}
void reset(){
memset(root, 0, sizeof(root));
cnt = -1; new_node();
root[0] = new_node();
}
void ins(int pre, int &rt, int l, int r, int k, int val){
rt = new_node();
nd[rt].val = nd[pre].val+val;
if (l == r) return;
int mid = (l+r)>>1;
if (k <= mid){
nd[rt].rs = nd[pre].rs;
ins(nd[pre].ls, nd[rt].ls, l, mid, k, val);
}
else{
nd[rt].ls = nd[pre].ls;
ins(nd[pre].rs, nd[rt].rs, mid+1, r, k, val);
}
}
int rank(int pre, int rt, int l, int r, int val){
if (val < l) return 0;
if (val > r) return nd[rt].val-nd[pre].val;
if (l == r) return 1;
int ret = 0, mid = (l+r)>>1;
ret += rank(nd[pre].ls, nd[rt].ls, l, mid, val);
ret += rank(nd[pre].rs, nd[rt].rs, mid+1, r, val);
return ret;
}
int k_th(int pre, int rt, int l, int r, int k){
if (l == r) return l;
int mid = (l+r)>>1, tmp = nd[nd[rt].ls].val-nd[nd[pre].ls].val;
if (tmp >= k)
return k_th(nd[pre].ls, nd[rt].ls, l, mid, k);
else return k_th(nd[pre].rs, nd[rt].rs, mid+1, r, k-tmp);
}
};
6.1.2可持久化线段树(主席树)
upd.2019.9.29
const int N = ;
const int E = ;
const int PN = N * E;
namespace Zhuxi_tree
{
int cnt, root[N], ch[PN][2], val[PN];
void reset(){
cnt = 0;
}
void push_up(int u){
}
void build(int &u, int l, int r, int *a){
if (u == 0) u = ++ cnt;
if (l == r){
// change
return;
}
int mid = (l + r) >> 1;
build(ch[u][0], l, mid, a);
build(ch[u][1], mid+1, r, a);
push_up(u);
}
void insert(int &u, int v, int l, int r, int P, int X){
if (u == 0) u = ++ cnt;
if (l == r){
// change
return;
}
int mid = (l + r) >> 1;
if (P <= mid){
insert(ch[u][0], ch[v][0], l, mid, P, X);
ch[u][1] = ch[v][1];
}
else{
insert(ch[u][1], ch[v][1], mid+1, r, P, X);
ch[u][0] = ch[v][0];
}
push_up(u);
}
}
using namespace Zhuxi_tree;
6.2可持久化并查集
upd.2019.9.29
基于可持久化数组,O(nlog^2n)
const int N = ;
const int E = ;
const int PN = N * E;
namespace Zhuxi_tree
{
int cnt, root[N], ch[PN][2], fa[PN], dep[PN];
void reset(){
cnt = 0;
}
void build(int &u, int l, int r){
if (u == 0) u = ++ cnt;
if (l == r){
fa[u] = l; dep[u] = 1;
return;
}
int mid = (l + r) >> 1;
build(ch[u][0], l, mid);
build(ch[u][1], mid+1, r);
}
void insert(int &u, int v, int l, int r, int P, int X){
if (u == 0) u = ++ cnt;
if (l == r){
fa[u] = X;
return;
}
int mid = (l + r) >> 1;
if (P <= mid){
insert(ch[u][0], ch[v][0], l, mid, P, X);
ch[u][1] = ch[v][1];
}
else{
insert(ch[u][1], ch[v][1], mid+1, r, P, X);
ch[u][0] = ch[v][0];
}
}
void update(int u, int l, int r, int P, int X){
if (l == r){
++ dep[u];
return;
}
int mid = (l + r) >> 1;
if (P <= mid) update(ch[u][0], l, mid, P, X);
else update(ch[u][1], mid+1, r, P, X);
}
int query(int u, int l, int r, int P){
if (l == r) return u;
int mid = (l + r) >> 1;
if (P <= mid) return query(ch[u][0], l, mid, P);
else return query(ch[u][1], mid+1, r, P);
}
}
using namespace Zhuxi_tree;
int Find(int x, int rt)
{
int fax = fa[query(rt, 1, n, x)];
if (fax == x) return x;
return Find(fax, rt);
}
6.3可持久化fhq Treap
upd.2019.10.24
注意E
要开两倍的log
,因为有些操作要split
两次。
namespace fhq_treap
{
const int N = , E = ;
int root[N], ncnt, ran[N*E], val[N*E], cnt[N*E], ch[N*E][2];
void reset(){
srand(time(0));
ncnt = 0;
root[0] = 0;
}
int newnode(int _val, int _cnt){
val[++ncnt] = _val;
cnt[ncnt] = _cnt;
ran[ncnt] = rand();
ch[ncnt][0] = ch[ncnt][1] = 0;
return ncnt;
}
int copy(int _ncnt){
val[++ncnt] = val[_ncnt];
cnt[ncnt] = cnt[_ncnt];
ran[ncnt] = ran[_ncnt];
ch[ncnt][0] = ch[_ncnt][0];
ch[ncnt][1] = ch[_ncnt][1];
return ncnt;
}
void push_up(int u){
cnt[u] = cnt[ch[u][0]] + cnt[ch[u][1]] + 1;
}
void split_val(int rt, int &u, int &v, int _val){ // (-inf, _val], [_val+1, +inf)
if (rt == 0){
u = v = 0; return;
}
if (val[rt] <= _val){
u = copy(rt);
split_val(ch[rt][1], ch[u][1], v, _val);
push_up(u);
}
else{
v = copy(rt);
split_val(ch[rt][0], u, ch[v][0], _val);
push_up(v);
}
}
void split_cnt(int rt, int &u, int &v, int _cnt){ // (-inf, _cnt], [_cnt+1, +inf)
if (rt == 0){
u = v = 0; return;
}
if (cnt[ch[rt][0]]+1 <= _cnt){
u = copy(rt);
split_cnt(ch[rt][1], ch[u][1], v, _cnt-cnt[ch[rt][0]]-1);
push_up(u);
}
else{
v = copy(rt);
split_cnt(ch[rt][0], u, ch[v][0], _cnt);
push_up(v);
}
}
int merge(int u, int v){
if (!u || !v) return u ^ v;
if (ran[u] < ran[v]){
ch[u][1] = merge(ch[u][1], v);
push_up(u);
return u;
}
else{
ch[v][0] = merge(u, ch[v][0]);
push_up(v);
return v;
}
}
}
using namespace fhq_treap;
7计算几何
7.1凸包
const double eps = 1e-9;
bool equ(double x, double y){return fabs(x-y) < eps;}
struct POINT{
double x, y;
POINT(){}
POINT(double a, double b){
x = a; y = b;
}
POINT operator - (POINT u){
return POINT(x-u.x, y-u.y);
}
};
double Cross(POINT u, POINT v){
return v.x*u.y-u.x*v.y;
}
struct CONVEX_HULL{
POINT a[N];
int n;
void clear(){
n = 0;
}
void insert(POINT u, bool fl){ // fl = 0 -> up /1 -> down
while (n >= 2){
double tmp = Cross(a[n]-a[n-1], u-a[n]);
if ((fl ? tmp > 0 : tmp < 0) || equ(tmp, 0)) -- n;
else break;
}
a[++ n] = u;
}
};
8后缀数组
#include<bits/stdc++.h>
using namespace std;
const int N = 1<<15;
const int E = 15;
namespace SA
{
int y[N], bin[N];
void get_sa(int *a, int *sa, int *rk, int n, int maxbin){
memset(bin, 0, sizeof(bin));
for (int i = 1; i <= n; ++ i)
++ bin[rk[i] = a[i]];
for (int i = 2; i <= maxbin; ++ i)
bin[i] += bin[i-1];
for (int i = n; i >= 1; -- i)
sa[bin[rk[i]]--] = i;
for (int l = 1; l <= n; l <<= 1){
int cnt = 0;
for (int i = n-l+1; i <= n; ++ i)
y[++ cnt] = i;
for (int i = 1; i <= n; ++ i)
if (sa[i] > l)
y[++ cnt] = sa[i]-l;
for (int i = 1; i <= maxbin; ++ i)
bin[i] = 0;
for (int i = 1; i <= n; ++ i)
++ bin[rk[i]];
for (int i = 2; i <= maxbin; ++ i)
bin[i] += bin[i-1];
for (int i = n; i >= 1; -- i)
sa[bin[rk[y[i]]]--] = y[i];
maxbin = y[sa[1]] = 1;
for (int i = 2; i <= n; ++ i)
y[sa[i]] = (rk[sa[i]] == rk[sa[i-1]] && rk[sa[i]+l] == rk[sa[i-1]+l]) ? maxbin : ++ maxbin;
for (int i = 1; i <= n; ++ i)
rk[i] = y[i];
if (maxbin == n) break;
}
}
void get_ht(int *a, int *sa, int *rk, int *ht, int n){
ht[0] = ht[n+1] = 0;
for (int i = 1; i <= n; ++ i){
if (rk[i] == 1) ht[1] = 0;
else{
int cnt = max(0, ht[rk[i-1]]-1), pre = sa[rk[i]-1];
while (a[i+cnt] == a[pre+cnt]) ++ cnt;
ht[rk[i]] = cnt;
}
}
}
void get_st(int *ht, int st[][N], int n){
for (int i = 1; i <= n; ++ i)
st[0][i] = ht[i];
for (int i = 1; (1<<i) <= n; ++ i)
for (int j = 1; j+(1<<i)-1 <= n; ++ j)
st[i][j] = min(st[i-1][j], st[i-1][j+(1<<(i-1))]);
}
int get_pref(int x, int y, int *rk, int st[][N], int n){ // x and y are the positions in initial string
x = rk[x]; y = rk[y];
if (x == y) return n-x+1;
if (x > y) swap(x, y);
++ x;
int lg = log2(y-x+1);
return min(st[lg][x], st[lg][y-(1<<lg)+1]);
}
}
using namespace SA;
/*
functions:
1. void get_sa(int *a, int *sa, int *rk, int n, int maxbin)
2. void get_ht(int *a, int *sa, int *rk, int *ht, int n)
3. void get_st(int *ht, int st[][N], int n)
4. int get_pref(int x, int y, int *rk, int st[][N], int n)
The key of arrays strat from 1!
Have fun!
*/
int n, k, a[N], rk[N], sa[N], ht[N], st[E][N];
9Trie树
9.1 01-trie
upd.2019.10.7
struct TRIE{
int ch[N*E][2], cnt;
void reset(){
cnt = 1;
memset(ch, 0, sizeof(ch));
}
void insert(LL x){
int now = 1;
for (int i = E-1; i >= 0; -- i){
int dig = (x >> i) & 1;
if (!ch[now][dig]) ch[now][dig] = ++cnt;
now = ch[now][dig];
}
}
LL query(LL x){
LL ret = 0; int now = 1;
for (int i = E-1; i >= 0; -- i){
int dig = (x >> i) & 1;
if (ch[now][dig]) now = ch[now][dig];
else ret ^= 1LL << i, now = ch[now][dig^1];
}
return ret;
}
};
10网络流
10.1 ISAP
#include<bits/stdc++.h>
using namespace std;
const int inf = ;
const int N = ;
const int M = ;
struct G{
int h[N], e, nxt[M], v[M], f[M];
void clear(){
e = 1;
memset(h, 0, sizeof(h));
}
void add_dir(int _u, int _v, int _f){
nxt[++e] = h[_u];
v[e] = _v; f[e] = _f;
h[_u] = e;
}
void add(int _u, int _v, int _f){
add_dir(_u, _v, _f);
add_dir(_v, _u, 0);
}
}g;
int n, s, t;
int dep[N], gap[N], cur[N];
void get_input()
{
// 读入+建图
}
int que[N], ql, qr;
void init()
{
for (int i = s; i <= t; ++ i)
cur[i] = g.h[i];
memset(gap, 0, sizeof(gap));
memset(dep, 0, sizeof(dep));
++ gap[dep[t] = 1];
que[ql = qr = 1] = t;
while (ql <= qr){
int u = que[ql++];
for (int i = g.h[u]; i; i= g.nxt[i]){
int v = g.v[i];
if (dep[v]) continue;
++gap[dep[v] = dep[u]+1];
que[++qr] = v;
}
}
}
int aug(int u, int maxf)
{
if (u == t) return maxf;
int nowf = 0;
for (int &i = cur[u]; i; i = g.nxt[i]){
int v = g.v[i], f = g.f[i];
if (dep[v] != dep[u]-1 || f == 0) continue;
int tmp = aug(v, min(maxf-nowf, f));
nowf += tmp;
g.f[i] -= tmp;
g.f[i^1] += tmp;
if (nowf == maxf) return nowf;
}
if (--gap[dep[u]] == 0) dep[s] = n+1;
++gap[++dep[u]];
cur[u] = g.h[u];
return nowf;
}
int isap()
{
init();
int ret = 0;
while (dep[s] <= n) ret += aug(s, inf);
return ret;
}
int main()
{
get_input();
printf("%d\n", isap());
return 0;
}
10.2Dinic
#include<bits/stdc++.h>
using namespace std;
const int inf = ;
const int N = ;
const int M = ;
struct G{
int h[N], e, nxt[M], v[M], f[M];
void clear(){
e = 1;
memset(h, 0, sizeof(h));
}
void add_dir(int _u, int _v, int _f){
nxt[++e] = h[_u];
v[e] = _v; f[e] = _f;
h[_u] = e;
}
void add(int _u, int _v, int _f){
add_dir(_u, _v, _f);
add_dir(_v, _u, 0);
}
}g;
int n, m, s, t;
int dep[N], cur[N];
void get_input()
{
// change
}
int que[N], ql, qr;
bool init()
{
for (int i = 1; i <= n; ++ i) // change
cur[i] = g.h[i];
memset(dep, 0, sizeof(dep));
dep[s] = 1;
que[ql = qr = 1] = s;
while (ql <= qr){
int u = que[ql++];
for (int i = g.h[u]; i; i= g.nxt[i]){
int v = g.v[i], f = g.f[i];
if (dep[v] || !f) continue;
dep[v] = dep[u]+1;
if (v == t) return true;
que[++qr] = v;
}
}
return false;
}
int aug(int u, int maxf)
{
if (u == t) return maxf;
int nowf = 0;
for (int &i = cur[u]; i; i = g.nxt[i]){
int v = g.v[i], f = g.f[i];
if (dep[v] != dep[u]+1 || f == 0) continue;
int tmp = aug(v, min(maxf-nowf, f));
nowf += tmp;
g.f[i] -= tmp;
g.f[i^1] += tmp;
if (nowf == maxf) return nowf;
}
return nowf;
}
int dinic()
{
int ret = 0;
while (init()) ret += aug(s, inf);
return ret;
}
int main()
{
get_input();
printf("%d\n", dinic());
return 0;
}
10.3费用流
#include<bits/stdc++.h>
using namespace std;
const int inf = ;
const int N = ;
const int M = ;
struct G{
int h[N], e, nxt[M], v[M], f[M], w[M];
void clear(){
e = 1;
memset(h, 0, sizeof(h));
}
void add_dir(int _u, int _v, int _f, int _w){
nxt[++e] = h[_u];
v[e] = _v; f[e] = _f; w[e] = _w;
h[_u] = e;
}
void add(int _u, int _v, int _f, int _w){
add_dir(_u, _v, _f, _w);
add_dir(_v, _u, 0, -_w);
}
}g;
int n, s, t;
void get_input()
{
// 读入+建图
}
queue<int> que;
int dis[N], pre[N], flo[N];
bool inq[N];
bool spfa()
{
memset(dis, 0x7f, sizeof(dis));
memset(flo, 0x7f, sizeof(flo));
que.push(s); dis[s] = 0; inq[s] = 1;
while (!que.empty()){
int u = que.front();
que.pop(); inq[u] = 0;
for (int i = g.h[u]; i; i = g.nxt[i]){
int v = g.v[i], f = g.f[i], w = g.w[i];
if (f && dis[v] > dis[u]+w){
dis[v] = dis[u]+w;
pre[v] = i;
flo[v] = min(f, flo[u]);
if (!inq[v]){inq[v] = 1; que.push(v);}
}
}
}
return dis[t] < inf;
}
int aug()
{
int u = t;
while (u != s){
int i = pre[u];
g.f[i] -= flo[t];
g.f[i^1] += flo[t];
u = g.v[i^1];
}
return dis[t]*flo[t];
}
int min_cost_max_flow()
{
int ret = 0;
while (spfa())
ret += aug();
return ret;
}
int main()
{
get_input();
printf("%d\n", min_cost_max_flow());
return 0;
}
11后缀自动机
const int PN = , S = ;
namespace SAM
{
int fa[PN], ch[PN][S], len[PN], cnt, last;
inline void reset(){
last = cnt = 1;
}
inline void copy(int x, int y){
for (int i = 0; i < S; ++ i)
ch[y][i] = ch[x][i];
fa[y] = fa[x];
}
inline void extend(int x){
x -= 'a';
int p = last, np = ++cnt;
last = np;
len[np] = len[p]+1;
while (p && !ch[p][x]) ch[p][x] = np, p = fa[p];
if (!p) fa[np] = 1;
else{
int q = ch[p][x];
if (len[q] == len[p]+1) fa[np] = q;
else{
int nq = ++cnt;
copy(q, nq);
len[nq] = len[p]+1;
fa[q] = fa[np] = nq;
while (p && ch[p][x] == q) ch[p][x] = nq, p = fa[p];
}
}
}
}
12LCT(动态树)
namespace LCT
{
const int N = 3e5+10;
int n, fa[N], ch[N][2], val[N], sum[N], flp[N];
inline bool is_root(int x){return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}
inline int son(int x){return ch[fa[x]][1] == x;}
inline void reverse(int u){swap(ch[u][0], ch[u][1]); flp[u] ^= 1;}
inline void push_up(int u){sum[u] = sum[ch[u][0]] ^ sum[ch[u][1]] ^ val[u];}
inline void push_down(int u){
if (flp[u]){
if (ch[u][0]) reverse(ch[u][0]);
if (ch[u][1]) reverse(ch[u][1]);
flp[u] = 0;
}
}
void pre_push_down(int u){
if (!is_root(u)) pre_push_down(fa[u]);
push_down(u);
}
inline void rotate(int u){
int v = fa[u], w = fa[v];
int vs = son(u), ws = son(v);
if (!is_root(v)) ch[w][ws] = u;
fa[v] = u;
ch[v][vs] = ch[u][vs^1];
fa[ch[u][vs^1]] = v;
fa[u] = w;
ch[u][vs^1] = v;
push_up(v); push_up(u);
}
inline void splay(int u){
pre_push_down(u);
for (; !is_root(u); rotate(u))
if (!is_root(fa[u]))
rotate(son(u) == son(fa[u]) ? fa[u] : u);
}
inline void access(int u){
for (int v = 0; u; v = u, u = fa[u])
splay(u), ch[u][1] = v, push_up(u);
}
inline void make_root(int u){
access(u); splay(u); reverse(u);
}
}
13数论模板
13.1最小公约数gcd
template<class T> inline T gcd(T x, T y){T r; while (y){r=x%y; x=y; y=r;} return x;}
13.2拓欧exgcd
upd.2019.10.9
template<class T> T exgcd(T x, T y, T &a, T &b)
{
if (y == 0){
a = 1; b = 0;
return x;
}
T _a, _b;
T g = exgcd(y, x % y, _a, _b);
a = _b;
b = _a - x / y * _b;
return g;
}
13.3快速幂
template<class T> inline T fpow(T x, T y, T p){
T r = 1;
while (y){
if (y&1) r = 1LL*r*x%p;
x = 1LL*x*x%p;
y >>= 1;
}
return r;
}
13.4BSGS和ex_BSGS
需要gcd
和fpow
,需要-stdc=++11
unordered_map<int, int> mp;
inline int ex_BSGS(int a, int b, int p)
{
a %= p; b %= p;
int x = 0, s = 1, g, d, k;
while ((g = gcd(a, p)) > 1){
if (b == s) return x;
if (b % g) return -1;
b /= g; p /= g; s = 1LL * s * a / g % p; ++ x;
}
d = sqrt(p) + 1; k = fpow(a, d, p);
mp.clear();
for (int i = 0, t = b; i <= d; ++ i, t = 1LL * t * a % p)
mp[t] = i;
for (int i = 1, t = 1LL * k * s % p; i <= d; ++ i, t = 1LL * t * k % p)
if (mp.count(t))
return d * i - mp[t] + x;
return -1;
}
13.5单个欧拉函数
upd.2019.8.9
O
(
n
)
O(\sqrt{n})
O(n)
template<class T>inline T get_phi(T x)
{
T ret = x;
for (int i = 2, ub = sqrt(x); i <= ub; ++ i){
if (x % i == 0) ret = ret / i * (i - 1);
while (x % i == 0) x /= i;
}
if (x > 1) ret = ret / x * (x - 1);
return ret;
}
13.6 组合数1
O(n)预处理,O(1)查询。
const int N = ;
const int mod = ;
namespace Combination
{
int fr[N], ifr[N];
int fpow(int x, int y){
int ret = 1;
while (y){
if (y & 1) ret = 1LL * ret * x % mod;
x = 1LL * x * x % mod;
y >>= 1;
}
return ret;
}
void init(){
fr[0] = 1;
for (int i = 1; i < N; ++ i)
fr[i] = 1LL * fr[i-1] * i % mod;
ifr[N-1] = fpow(fr[N-1], mod-2);
for (int i = N-2; i >= 0; -- i)
ifr[i] = 1LL * ifr[i+1] * (i+1) % mod;
}
int C(int x, int y){
return 1LL * fr[x] * ifr[y] % mod * ifr[x-y] % mod;
}
}
using namespace Combination;
13.7卢卡斯定理
upd.2019.10.9
namespace Lucas
{
const int N = 1e5 + 10;
int fr[N], ifr[N];
int fpow(int x, int y, int p){
int ret = 1;
while (y){
if (y & 1) ret = 1LL * ret * x % p;
x = 1LL * x * x % p;
y >>= 1;
}
return ret;
}
void init(int n, int p){
fr[0] = 1;
for (int i = 1; i <= n; ++ i)
fr[i] = 1LL * fr[i-1] * i % p;
ifr[n] = fpow(fr[n], p-2, p);
for (int i = n-1; i >= 0; -- i)
ifr[i] = 1LL * ifr[i+1] * (i+1) % p;
}
int Lucas(int n, int m, int p){
if (n < p && m < p) return 1LL * fr[n] * ifr[m] % p * ifr[n-m] % p;
return 1LL * Lucas(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}
}
13.8拓展卢卡斯定理
upd.2019.10.9
namespace exLucas
{
typedef long long LL;
LL M, ans;
LL fpow(LL x, LL y, LL p){
LL ret = 1;
while (y){
if (y & 1) ret = ret * x % p;
x = x * x % p;
y >>= 1;
}
return ret;
}
LL exgcd(LL x, LL y, LL &a, LL &b){
if (y == 0){
a = 1; b = 0;
return x;
}
LL _a, _b;
LL g = exgcd(y, x % y, _a, _b);
a = _b;
b = _a - x / y * _b;
return g;
}
LL inv(LL x, LL p){
LL tmp1, tmp2;
exgcd(x, p, tmp1, tmp2);
return (tmp1 % p + p) % p;
}
LL fac(LL n, LL p, LL pk){
if (n == 0) return 1;
LL ret = 1;
for (LL i = 2; i < pk; ++ i) if (i%p) (ret *= i) %= pk;
ret = fpow(ret, n/pk, pk);
for (LL i = 2, sz = n%pk; i <= sz; ++ i) if (i%p) (ret *= i) %= pk;
return ret * fac(n / p, p, pk) % pk;
}
LL C(LL n, LL m, LL p, LL pk){
LL cnt = 0;
for (LL i = n; i; i /= p) cnt += i / p;
for (LL i = m; i; i /= p) cnt -= i / p;
for (LL i = n-m; i; i /= p) cnt -= i / p;
return fac(n, p, pk) * inv(fac(m, p, pk), pk) % pk * inv(fac(n-m, p, pk), pk) % pk * fpow(p, cnt, pk) % pk;
}
LL CRT(LL a, LL b){return a * inv(M / b, b) % M * (M / b) % M;}
LL exLucas(LL n, LL m, LL p){
M = p; ans = 0;
for (LL i = 2, sz = sqrt(p) + 1; i <= sz; ++ i)
if (p % i == 0){
LL pk = 1;
while (p % i == 0)
pk *= i, p /= i;
(ans += CRT(C(n, m, i, pk), pk)) %= M;
}
if (p > 1) (ans += CRT(C(n, m, p, p), p)) %= M;
return ans;
}
}
14manacher
int manacher(int n, char *s, int *p)
{
for (int i = n-1; i >= 0; -- i)
s[(i+1)<<1] = s[i], s[((i+1)<<1)+1] = '#';
n = (n+1)<<1;
s[0] = '$'; s[1] = '#'; s[n] = '\0';
int id, mx = -1, ret = 0;
for (int i = 0; i < n; ++ i){
if (i <= mx) p[i] = min(p[(id<<1)-i], mx-i);
else p[i] = 1;
while (s[i+p[i]] == s[i-p[i]]) ++ p[i];
if (i+p[i]-1 > mx){
mx = i+p[i]-1;
id = i;
}
ret = max(ret, p[i]-1);
}
return ret;
}
15线段树
15.0原始
namespace Seg_tr
{
#define ls (u<<1)
#define rs (u<<1^1)
int t[N<<2]; // laz[N<<2];
void push_up(int u){
}
void push_down(int u){
}
void build(int u, int l, int r, int *a){
}
void modify_point(int u, int l, int r, int P, int X){
}
void modify_interval(int u, int l, int r, int L, int R, int X){
}
int query(int u, int l, int r, int L, int R){
}
#undef ls
#undef rs
}
15.1区间求和(结构体)
upd.2019.10.7
struct Sum_tr{
#define ls (u<<1)
#define rs (u<<1^1)
int t[N<<2], laz[N<<2];
void push_up(int u){
t[u] = t[ls] + t[rs];
}
void push_down(int u, int ln, int rn){
if (laz[u]){
t[ls] += laz[u] * ln;
laz[ls] += laz[u];
t[rs] += laz[u] * rn;
laz[rs] += laz[u];
laz[u] = 0;
}
}
void build(int u, int l, int r, int *a){
if (l == r){
t[u] = a[l];
return;
}
int mid = l + r >> 1;
build(ls, l, mid, a);
build(rs, mid+1, r, a);
push_up(u);
}
void modify(int u, int l, int r, int L, int R, int X){
if (L <= l && r <= R){
t[u] += (r - l + 1) * X;
laz[u] += X;
return;
}
int mid = l + r >> 1;
push_down(u, mid-l+1, r-mid);
if (L <= mid) modify(ls, l, mid, L, R, X);
if (mid < R) modify(rs, mid+1, r, L, R, X);
push_up(u);
}
int query(int u, int l, int r, int L, int R){
if (L <= l && r <= R)
return t[u];
int mid = l + r >> 1, ret = 0;
push_down(u, mid-l+1, r-mid);
if (L <= mid) ret += query(ls, l, mid, L, R);
if (mid < R) ret += query(rs, mid+1, r, L, R);
return ret;
}
#undef ls
#undef rs
}s;
16点分治
upd.2019.8.9
需要图(不用结构体)
const int N = ;
const int M = ;
namespace Graph
{
int h[N], ecnt, nxt[M], v[M];
void clear(){ecnt = 1;}
void add_dir(int _u, int _v){
v[++ecnt] = _v;
nxt[ecnt] = h[_u]; h[_u] = ecnt;
}
void add_undir(int _u, int _v){
add_dir(_u, _v);
add_dir(_v, _u);
}
}
using namespace Graph;
namespace Tree_div
{
int siz[N], zx, mins, sizn;
bool vis[N];
void get_zx(int u, int fa)
{
int sons = 0;
siz[u] = 1;
for (int i = h[u]; i; i = nxt[i])
if (v[i] != fa && !vis[v[i]]){
get_zx(v[i], u);
siz[u] += siz[v[i]];
if (siz[v[i]] >= sons) sons = siz[v[i]];
}
if (sons < sizn - siz[u]) sons = sizn - siz[u];
if (sons < mins) mins = sons, zx = u;
}
void calc(int u, int fa, int fl)
{ // change
for (int i = h[u]; i; i = nxt[i])
if (v[i] != fa && !vis[v[i]]){
calc(v[i], u, fl);
}
}
void solve(int u)
{
vis[u] = 1;
for (int i = h[u]; i; i = nxt[i])
if (!vis[v[i]]){
// change
}
for (int i = h[u]; i; i = nxt[i])
if (!vis[v[i]]){
mins = inf; sizn = siz[v[i]];
get_zx(v[i], u);
solve(zx);
}
}
}
using namespace Tree_div;
17 LCA
upd.2019.10.29
需要预处理 dep[u]
和 f[u][i]
。
int lca(int x, int y)
{
if (dep[x] < dep[y]) swap(x, y);
for (int i = E-1; i >= 0; -- i)
if (dep[f[x][i]] >= dep[y])
x = f[x][i];
if (x == y) return x;
for (int i = E-1; i >= 0; -- i)
if (f[x][i] != f[y][i])
x = f[x][i], y = f[y][i];
return f[x][0];
}
FWT
位运算卷积
upd.2019.12.18
void FWT_or(int *A, bool opt){
for (int i = 2; i <= e; i <<= 1)
for (int j = 0; j < e; j += i)
for (int k = 0, qw = i>>1; k < qw; ++ k){
if (opt) add(A[j+k+qw], A[j+k]);
else add(A[j+k+qw], mod-A[j+k]);
}
}
void FWT_and(int *A, bool opt){
for (int i = 2; i <= e; i <<= 1)
for (int j = 0; j < e; j += i)
for (int k = 0, qw = i>>1; k < qw; ++ k){
if (opt) add(A[j+k], A[j+k+qw]);
else add(A[j+k], mod-A[j+k+qw]);
}
}
void FWT_xor(int *A, bool opt){
int inv2 = fpow(2, mod-2);
for (int i = 2; i <= e; i <<= 1)
for (int j = 0; j < e; j += i)
for (int k = 0, qw = i>>1; k < qw; ++ k){
int A0 = A[j+k], A1 = A[j+k+qw];
if (opt) A[j+k] = (A0+A1)%mod, A[j+k+qw] = (A0-A1+mod)%mod;
else A[j+k] = 1LL*(A0+A1)*inv2%mod, A[j+k+qw] = 1LL*(A0-A1+mod)*inv2%mod;
}
}