各种模板

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

需要gcdfpow,需要-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;
			}
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值