代码相关

upd on 26.3.4 代码风格由

const int maxn = 100005;
int a[maxn];

改为

const int maxn = 100000;
int a[maxn + 5];

以前代码有时间就该过来吧

缺省源

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctime>
#include<vector>
#define mp make_pair
#define chkmax(a , b) a = max(a , b)
#define chkmin(a , b) a = min(a , b)
#define fo(i , x , y) for(int i = x ; i <= y ; i++)
#define go(i , x , y) for(int i = x ; i >= y ; i--)
#define local
#ifdef local
#define debug(x) cerr << #x" : " << x << ", "
#define debugn(x) cerr << #x" : " << x << "\n"
#define debugs(s) cerr << s
#define debugarr(a , n); cerr << #a" : \n"; fo(i , 1 , n) cerr << a[i] << " "; cerr << "\n";
#else
#define debug(x) "n-buna bless me."
#define debugn(x) "Nayutan bless me."
#define debugs(s) "Deco*27 bless me."
#define debugarr(a , n) "wowaka bless me."
#endif
using namespace std;
int main(){
    // clock_t starttime = clock();
    ios :: sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
    // freopen(".in" , "r" , stdin);
    // freopen(".out" , "w" , stdout);
    
    // clock_t endtime = clock();
    // double elapsed = static_cast<double>(endtime - starttime) / CLOCKS_PER_SEC;
    // debugn(elapsed);
}

数据结构

树状数组

const int maxn = 100000;
struct Fenwick_Tree{
	private:
	int t[maxn + 5];
	int lowbit(int x){
		return x & -x;
	}
	public:
	void updata(int x , int v){
		for(int i = x ; i <= n ; i += lowbit(i))
			t[i] += v;
	}
	int query(int x){
		int ans = 0;
		for(int i = x ; i ; i -= lowbit(i))
			ans += t[i];
		return ans;
	}
	int query(int l , int r){
		return query(r) - query(l - 1);
	}
};

线段树

从之前普通的版本改为动态开点

struct node{
    friend node operator + (const node a , const node b){

    }
};
struct Segment_Tree{
    private:
    int cnt , ls[maxn * 2 + 5] , rs[maxn * 2 + 5];
    int lazy[maxn * 2 + 5];
    node t[maxn * 2 + 5];
    void modify(int v1 , int l , int r , int k){
        
    }
    void pushdown(int l , int r , int k){
        int mid = (l + r) / 2;
        if(ls[k] == 0) ls[k] = build(l , mid);
        if(rs[k] == 0) rs[k] = build(mid + 1 , r);
        modify(lazy[k] , l , mid , ls[k]);
        modify(lazy[k] , mid + 1 , r , rs[k]);
        lazy[k] = 0;
    }
    public:
    int build(int l , int r){
        int k = ++cnt;
        // init t[k] and lazy[k]
        return k;
    }
    void update(int L , int R , int v1 , int l , int r , int k){
        if(L > R) return;
        if(L <= l and r <= R){
            modify(v1 , l , r , k);
            return;
        }
        pushdown(l , r , k);
        int mid = (l + r) / 2;
        if(L <= mid) update(L , R , v1 , l , mid , ls[k]); 
        if(mid + 1 <= R) update(L , R , v1 , mid + 1 , r , rs[k]);
        t[k] = t[ls[k]] + t[rs[k]];
    }
    node query(int L , int R , int l , int r , int k){
        if(L <= l and r <= R) return t[k];
        pushdown(l , r , k);
        int mid = (l + r) / 2;
        if(L <= mid){
            node ans = query(L , R , l , mid , ls[k]);
            if(mid + 1 <= R) return ans + query(L , R , mid + 1 , r , rs[k]);
            else return ans;
        }
        else return query(L , R , mid + 1 , r , rs[k]);
    }
}tr;

可持久化线段树

const int maxn = 100000;
const int maxp = 100000;
const int maxnode = maxp * 2 + maxn * 20 + 5;
struct node{
    long long sump , suml;
    friend node operator + (const node a , const node b){
        return {a.sump + b.sump , a.suml + b.suml};
    }
};
struct Segment_Tree{
    private:
    int cnt , ls[maxnode] , rs[maxnode];
    node t[maxnode];
    void modify(int L , int l , int r , int k){
        t[k].suml += L;
        t[k].sump = t[k].suml * l;
    }
    public:
    int build(int l , int r){
        int k = ++cnt;
        // init t[k] and lazy[k]
        return k;
    }
    int update(int p , int L , int l , int r , int k){
        // debug(p) , debug(L) , debug(l) , debug(r) , debugn(k);
        int k2 = build(l , r);
        t[k2] = t[k];
        ls[k2] = ls[k] , rs[k2] = rs[k];
        if(l == r){
            modify(L , p , p , k2);
            return k2;
        }
        int mid = (l + r) / 2;
        if(p <= mid){
            if(ls[k] == 0) ls[k] = build(l , mid);
            ls[k2] = update(p , L , l , mid , ls[k]);
        }
        else{
            if(rs[k] == 0) rs[k] = build(mid + 1 , r);
            rs[k2] = update(p , L , mid + 1 , r , rs[k]);
        }
        t[k2] = t[ls[k2]] + t[rs[k2]];
        return k2;
    }
    long long query(long long L , int l , int r , int k){
        // debug(l) , debug(r) , debugn(k);
        if(l == r){
            if(t[k].suml < L) return -1;
            else return L * l;
        }
        int mid = (l + r) / 2;
        if(t[ls[k]].suml >= L) return query(L , l , mid , ls[k]);
        else{
            long long p2 = query(L - t[ls[k]].suml , mid + 1 , r , rs[k]);
            if(p2 == -1) return -1;
            return t[ls[k]].sump + p2;
        }
    }
}tr;
int rt[maxp + 5];

线段树其他

动态开点、权值线段树的合并,支持单点修改,线段树二分以查询 lower_bound

struct Segment_Tree{
    int cnt , ls[maxn * 20] , rs[maxn * 20];
    struct node{
        int sum , mx;
    }t[maxn * 20];
    node pushup(node a , node b){
        node ans = {a.sum + b.sum , max(a.mx , b.mx)};
        return ans;
    }
    int build(){
        return ++cnt;
    }
    void updata(int x , int v , int l , int r , int k){
        if(l == r){
            t[k].sum += v;
            if(t[k].sum) t[k].mx = l;
            else t[k].mx = 0;
            return;
        }
        int mid = (l + r) / 2;
        if(x <= mid){
            if(ls[k] == 0) ls[k] = ++cnt;
            updata(x , v , l , mid , ls[k]);
        }
        else{
            if(rs[k] == 0) rs[k] = ++cnt;
            updata(x , v , mid + 1 , r , rs[k]);
        }
        t[k] = pushup(t[ls[k]] , t[rs[k]]);
    }
    int query(int x , int l , int r , int k){
        // cerr << x << " " << l << " " << r << " " << k << "\n";
        if(r < x) return t[k].mx;
        if(l == r) return 0;
        int mid = (l + r) / 2;
        if(mid + 1 < x) return max(query(x , l , mid , ls[k]) , query(x , mid + 1 , r , rs[k]));
        else return query(x , l , mid , ls[k]);
    }
    int merge(int l , int r , int k1 , int k2){
        if(min(k1 , k2) == 0) return k1 + k2;
        if(l == r){
            t[k1].sum += t[k2].sum;
            if(t[k1].sum) t[k1].mx = l;
            else t[k1].mx = 0;
            return k1;
        }
        int mid = (l + r) / 2;
        ls[k1] = merge(l , mid , ls[k1] , ls[k2]);
        rs[k1] = merge(mid + 1 , r , rs[k1] , rs[k2]);
        t[k1] = pushup(t[ls[k1]] , t[rs[k1]]);
        return k1;
    }
}tr;

树套树

树状数组套动态开点线段树,维护单点加,矩阵查询

struct Segment_Tree{
    private:
    int cnt , ls[maxn * 80] , rs[maxn * 80];
    long long t[maxn * 80];
    public:
    int build(int l , int r){
        int k = ++cnt;
        t[k] = 0;
        return k;
    }
    void update(int x , int v1 , int l , int r , int k){
        if(l == r){
            t[k] += v1;
            return;
        }
        int mid = (l + r) / 2;
        if(x <= mid){
            if(ls[k] == 0) ls[k] = build(l , mid);
            update(x , v1 , l , mid , ls[k]);
        }
        else{
            if(rs[k] == 0) rs[k] = build(mid + 1 , r);
            update(x , v1 , mid + 1 , r , rs[k]);
        }
        t[k] = t[ls[k]] + t[rs[k]];
    }
    long long query(int L , int R , int l , int r , int k){
        if(k == 0) return 0;
        if(L <= l and r <= R) return t[k];
        int mid = (l + r) / 2;
        if(L <= mid){
            long long ans = query(L , R , l , mid , ls[k]);
            if(mid + 1 <= R) return ans + query(L , R , mid + 1 , r , rs[k]);
            else return ans;
        }
        else return query(L , R , mid + 1 , r , rs[k]);
    }
}tr;
struct Fenwick_Tree{
	private:
	int rt[maxn + 5];
	int lowbit(int x){
		return x & -x;
	}
	public:
    void init(){
        fo(i , 1 , n + 1) rt[i] = tr.build(1 , n + 1);
    }
	void update(int x , int y , int v){
        if(x > n + 1 or y > n + 1) return;
		for(int i = x ; i <= n + 1 ; i += lowbit(i))
			tr.update(y , v , 1 , n + 1 , rt[i]);
	}
	int query(int x , int l , int r){
		int ans = 0;
		for(int i = x ; i ; i -= lowbit(i))
			ans += tr.query(l , r , 1 , n + 1 , rt[i]);
		return ans;
	}
}tr2;

平衡树

无旋 treap

#include<ctime>
#include<random>
#define mp make_pair
const int maxn = 100000;
mt19937 rd(time(0));
struct Treap{
    private:
    int rt , cnt , num[maxn + 5] , siz[maxn + 5] , pri[maxn + 5] , ls[maxn + 5] , rs[maxn + 5];
    int build(int x){
        cnt++;
        num[cnt] = x , siz[cnt] = 1 , pri[cnt] = rd();
        ls[cnt] = rs[cnt] = 0;
        return cnt;
    }
    void pushup(int k){
        siz[k] = siz[ls[k]] + siz[rs[k]] + 1;
    }
    int merge(int k1 , int k2){
        if(min(k1 , k2) == 0) return max(k1 , k2);
        if(pri[k1] > pri[k2]){
            rs[k1] = merge(rs[k1] , k2);
            pushup(k1);
            return k1;
        }
        else{
            ls[k2] = merge(k1 , ls[k2]);
            pushup(k2);
            return k2;
        }
    }
    pair<int , int> split_val(int k , int key){
        if(k == 0) return mp(0 , 0);
        if(num[k] <= key){
            pair<int , int> tmp = split_val(rs[k] , key);
            rs[k] = tmp.first;
            pushup(k);
            return mp(k , tmp.second);
        }
        else{
            pair<int , int> tmp = split_val(ls[k] , key);
            ls[k] = tmp.second;
            pushup(k);
            return mp(tmp.first , k);
        }
    }
    pair<int , int> split_siz(int k , int key){
        if(k == 0) return mp(0 , 0);
        if(siz[ls[k]] + 1 <= key){
            pair<int , int> tmp = split_siz(rs[k] , key - siz[ls[k]] - 1);
            rs[k] = tmp.first;
            pushup(k);
            return mp(k , tmp.second);
        }
        else{
            pair<int , int> tmp = split_siz(ls[k] , key);
            ls[k] = tmp.second;
            pushup(k);
            return mp(tmp.first , k);
        }
    }
    public:
    void init(){
        rt = cnt = 0;
    }
    void insert(int x){
        int k2 = build(x);
        pair<int , int> tmp = split_val(rt , x);
        int k1 = tmp.first , k3 = tmp.second;
        rt = merge(k1 , merge(k2 , k3));
    }
    void del(int x){
        pair<int , int> tmp = split_val(rt , x - 1);
        int k1 = tmp.first , k23 = tmp.second;
        tmp = split_siz(k23 , 1);
        int k2 = tmp.first , k3 = tmp.second;
        rt = merge(k1 , k3);
    }
    int rank(int x){
        pair<int , int> tmp = split_val(rt , x - 1);
        int k1 = tmp.first , k2 = tmp.second;
        int ans = siz[k1] + 1;
        rt = merge(k1 , k2);
        return ans;
    }
    int query(int x){
        pair<int , int> tmp = split_siz(rt , x - 1);
        int k1 = tmp.first , k23 = tmp.second;
        tmp = split_siz(k23 , 1);
        int k2 = tmp.first , k3 = tmp.second;
        int ans = num[k2];
        rt = merge(k1 , merge(k2 , k3));
        return ans;
    }
    int pre(int x){
        pair<int , int> tmp = split_val(rt , x - 1);
        int k12 = tmp.first , k3 = tmp.second;
        tmp = split_siz(k12 , siz[k12] - 1);
        int k1 = tmp.first , k2 = tmp.second;
        int ans = num[k2];
        rt = merge(k1 , merge(k2 , k3));
        return ans;
    }
    int suf(int x){
        pair<int , int> tmp = split_val(rt , x);
        int k1 = tmp.first , k23 = tmp.second;
        tmp = split_siz(k23 , 1);
        int k2 = tmp.first , k3 = tmp.second;
        int ans = num[k2];
        rt = merge(k1 , merge(k2 , k3));
        return ans;
    }
};

有旋 treap

mt19937 rd(time(0));
struct Treap{
    private:
    int tot;
    int ls[maxn + 5] , rs[maxn + 5] , num[maxn + 5] , cnt[maxn + 5] , siz[maxn + 5] , pri[maxn + 5];
    void pushup(int k){
        siz[k] = siz[ls[k]] + siz[rs[k]] + cnt[k];
    }
    int rrotate(int k){
        int rt = ls[k];
        ls[k] = rs[rt];
        rs[rt] = k;
        pushup(k) , pushup(rt);
        return rt;
    }
    int lrotate(int k){
        int rt = rs[k];
        rs[k] = ls[rt];
        ls[rt] = k;
        pushup(k) , pushup(rt);
        return rt;
    }
    public:
    int insert(int k , int x){
        debug(k) , debugn(x);
        if(k == 0){
            k = ++tot;
            num[k] = x , cnt[k] = 1 , siz[k] = 1 , pri[k] = rd();
            return k;
        }
        if(x == num[k])
            cnt[k]++ , pushup(k);
        else if(x < num[k]){
            ls[k] = insert(ls[k] , x);
            pushup(k);
            if(pri[ls[k]] > pri[k]) k = rrotate(k);
        }
        else{
            rs[k] = insert(rs[k] , x);
            pushup(k);
            if(pri[rs[k]] > pri[k]) k = lrotate(k);
        }
        return k;
    }
    int del(int k , int x){
        debugs("del:") , debug(k) , debugn(num[k]);
        if(num[k] == x){
            if(cnt[k] > 1){
                cnt[k]--;
            }
            else if(min(ls[k] , rs[k]) == 0) return ls[k] + rs[k];
            else if(pri[ls[k]] > pri[rs[k]]){
                k = rrotate(k);
                rs[k] = del(rs[k] , x);
            }
            else{
                k = lrotate(k);
                ls[k] = del(ls[k] , x);
            }
        }
        else if(x < num[k]){
            ls[k] = del(ls[k] , x);
        }
        else{
            rs[k] = del(rs[k] , x);
        }
        pushup(k);
        return k;
    }
    int getrank(int k , int x){
        if(k == 0) return 1;
        if(x == num[k]) return siz[ls[k]] + 1;
        if(x < num[k]) return getrank(ls[k] , x);
        else return siz[ls[k]] + cnt[k] + getrank(rs[k] , x);
    }
    int getnum(int k , int rank){
        debug(k) , debug(num[k]) , debugn(rank);
        debug(num[ls[k]]) , debugn(num[rs[k]]);
        if(k == 0) return -inf;
        if(rank <= siz[ls[k]]) return getnum(ls[k] , rank);
        if(rank <= siz[ls[k]] + cnt[k]) return num[k];
        return getnum(rs[k] , rank - siz[ls[k]] - cnt[k]);
    }
    int getpre(int k , int x){
        if(k == 0) return -inf;
        if(num[k] < x){
            int ans = getpre(rs[k] , x);
            if(ans != -inf) return ans;
            else return num[k];
        }
        else return getpre(ls[k] , x);
    }
    int getnxt(int k , int x){
        if(k == 0) return -inf;
        if(num[k] > x){
            int ans = getnxt(ls[k] , x);
            if(ans != -inf) return ans;
            else return num[k];
        }
        else return getnxt(rs[k] , x);
    }
};

ST 表

\([i - 2^j + 1 , i]\) 的 st 表,可实现在线插入

int lg[maxn + 5];
void init(){
    lg[2] = 1;
    fo(i , 3 , maxn + 1)
        lg[i] = lg[i / 2] + 1;
}
struct Sparse_Table{
private:
    int st[18][maxn + 5];
public:
    void ins(int id , int num){
        st[0][id] = num;
        for(int j = 1 ; id - (1 << j) + 1 >= 1 ; j++){
            st[j][id] = max(st[j - 1][id] , st[j - 1][id - (1 << j - 1)]);
        }
    }
    int ask(int l , int r){
        if(l > r) return -inf;
        int k = lg[r - l + 1];
        return max(st[k][r] , st[k][l + (1 << k) - 1]);
    }
    void clear(){
        fo(j , 0 , 17)
            fo(i , 1 , n)
                st[j][i] = 0;
    }
}

李超线段树

现在只写了支持全局线段插入,区间插入的以后再写

struct func{
    long long a , b;
};
class lichao{
private:
    func t[maxn << 2];
    long long f(int x , func a){
        return a.a * x + a.b;
    }
public:
    void build(int l , int r , int k){
        t[k] = {0 , 0};
        if(l == r) return;
        int mid = (l + r) / 2;
        build(l , mid , k << 1) , build(mid + 1 , r , k << 1 | 1);
    }
    void insert(func x , int l , int r , int k){
        int mid = (l + r) / 2;
        if(f(mid , t[k]) < f(mid , x)) swap(t[k] , x);
        if(l == r) return;
        if(x.a < t[k].a) insert(x , l , mid , k << 1);
        else insert(x , mid + 1 , r , k << 1 | 1);
    }
    long long query(int x , int l , int r , int k){
        if(l == r) return f(x , t[k]);
        int mid = (l + r) / 2;
        long long ans = f(x , t[k]);
        if(x <= mid) return max(ans , query(x , l , mid , k << 1));
        else return max(ans , query(x , mid + 1 , r , k << 1 | 1));
    }
};

字符串

哈希

const int maxl = 1000000;
const int base1 = 131;
const int mod1 = 1000000007;
const int base2 = 233;
const int mod2 = 998244353;
int powbase1[maxl + 5] , powbase2[maxl + 5];
void init(){
    powbase1[0] = 1;
    fo(i , 1 , maxl) powbase1[i] = 1ll * powbase1[i - 1] * base1 % mod1;
    powbase2[0] = 1;
    fo(i , 1 , maxl) powbase2[i] = 1ll * powbase2[i - 1] * base2 % mod2;
}
struct mystring{
    private:
    string s;
    int len;
    pair<int , int> hsh[maxl + 5];
    void solve(){
        fo(i , 1 , len){
            hsh[i].first = (1ll * hsh[i - 1].first * base1 % mod1 + s[i]) % mod1;
            hsh[i].second = (1ll * hsh[i - 1].second * base2 % mod2 + s[i]) % mod2;
        }
    }
    public:
    void read(){
        cin >> s;
        len = s.size();
        s = " " + s;
        solve();
    }
    void init(string input){
        len = input.size();
        s = " " + input;
        solve();
    }
    pair<int , int> gethash(int l , int r){
        int ans1 = hsh[r].first;
        int tmp1 = 1ll * hsh[l - 1].first * powbase1[r - l + 1] % mod1;
        ans1 = (ans1 - tmp1 + mod1) % mod1;
        int ans2 = hsh[r].second;
        int tmp2 = 1ll * hsh[l - 1].second * powbase2[r - l + 1] % mod2;
        ans2 = (ans2 - tmp2 + mod2) % mod2;
        return mp(ans1 , ans2);
    }
    pair<int , int> gethash(){
        return hsh[len];
    }
};

KMP

string s;
int fail[maxl + 5];
for(int i = 2 , j = 0 ; i <= n ; i++){
    while(j and s[j + 1] != s[i]) j = fail[j];
    if(s[j + 1] == s[i]) j++;
    fail[i] = j;
}

SA

int rk[maxl + 5] , sa[maxl + 5] , oldrk[maxl + 5] , id[maxl + 5] , cnt[maxl + 5] , height[maxl + 5];
void getSA(){
    int m = 128 , p = 0;
    fo(i , 1 , n) cnt[rk[i] = s[i]]++;
    fo(i , 1 , m) cnt[i] += cnt[i - 1];
    fo(i , 1 , n) sa[cnt[rk[i]]--] = i;
    for(int w = 1 ; ; w *= 2 , m = p){
        int cur = 0;
        fo(i , n - w + 1 , n) id[++cur] = i;
        fo(i , 1 , n)
            if(sa[i] > w)
                id[++cur] = sa[i] - w;
        memset(cnt , 0 , sizeof(cnt));
        fo(i , 1 , n) cnt[rk[i]]++;
        fo(i , 1 , m) cnt[i] += cnt[i - 1];
        go(i , n , 1) sa[cnt[rk[id[i]]]--] = id[i];
        memcpy(oldrk , rk , sizeof(rk));
        p = 0;
        fo(i , 1 , n){
            if(oldrk[sa[i]] == oldrk[sa[i - 1]] and oldrk[sa[i] + w] == oldrk[sa[i - 1] + w])
                rk[sa[i]] = p;
            else rk[sa[i]] = ++p;
        }
        if(p == n) break;
    }
    int k = 0;
    fo(i , 1 , n){
        if(k) k--;
        while(s[i + k] == s[sa[rk[i] - 1] + k]) k++;
        height[rk[i]] = k;
    }
}

AC 自动机

int cnt = 1;
struct node{
    int son[maxv + 5] , fail;
    int len;
    bool flag;
}trie[maxl + 5];
void insert(string s){
    int u = 1 , len = s.size() - 1;
    fo(i , 1 , len){
        int c = s[i] - 'a' + 1;
        if(trie[u].son[c] == 0) trie[u].son[c] = ++cnt;
        u = trie[u].son[c];
    }
    trie[u].len = len;
    trie[u].flag = true;
}
void getfail(){
    fo(i , 1 , 26) trie[0].son[i] = 1;
    queue<int> q;
    q.push(1);
    while(q.size()){
        int u = q.front();
        q.pop();
        int fail = trie[u].fail;
        fo(i , 1 , 26){
            int& v = trie[u].son[i];
            if(v == 0){
                v = trie[fail].son[i];
                continue;
            }
            trie[v].fail = trie[fail].son[i];
            q.push(v);
        }
    }
}

图、树相关

点分树

vector<int> e[maxn + 5];
int siz[maxn + 5];
bool vis[maxn + 5];
int get_root(int u , int sum , int fa){
    int ans = -1;
    siz[u] = 1;
    bool flag = true;
    for(int v : e[u]){
        if(v == fa) continue;
        if(vis[v]) continue;
        int res = get_root(v , sum , u);
        if(res != -1) ans = res;
        if(siz[v] * 2 > sum) flag = false;
        siz[u] += siz[v];
    }
    if(ans != -1) return ans;
    if(flag and (sum - siz[u]) * 2 <= sum) return u;
    return -1;
}
void solve(int rt , int sum){
    vis[rt] = true;
    for(int v : e[rt]){
        if(vis[v]) continue;
        int sumv = (siz[v] < siz[rt] ? siz[v] : sum - siz[rt]);
        solve(get_root(v , sumv , 0) , sumv);
    }
}

重链剖分

有边权版本

struct Decomposition{
    int siz[maxn + 5] , fa[maxn + 5] , dep[maxn + 5] , son[maxn + 5] , top[maxn + 5] , idx , dfn[maxn + 5];
    long long dis[maxn + 5];
    void dfs1(int u , int f){
        siz[u] = 1 , fa[u] = f , dep[u] = dep[f] + 1;
        for(node x : e[u]){
            int v = x.v;
            if(v == f) continue;
            dis[v] = dis[u] + x.w;
            dfs1(v , u);
            siz[u] += siz[v];
            if(siz[v] > siz[son[u]]) son[u] = v;
        }
    }
    void dfs2(int u , int tp){
        top[u] = tp;
        dfn[u] = ++idx;
        if(son[u]) dfs2(son[u] , tp);
        for(node x : e[u]){
            int v = x.v;
            if(v == fa[u]) continue;
            if(v == son[u]) continue;
            dfs2(v , v);
        }
    }
    int lca(int u , int v){
        while(top[u] != top[v]){
            if(dep[top[u]] < dep[top[v]]) swap(u , v);
            u = fa[top[u]];
        }
        if(dep[u] < dep[v]) swap(u , v);
        return v;
    }
    long long get_dis(int u , int v){
        int f = lca(u , v);
        return dis[u] + dis[v] - dis[f] * 2;
    }
};

tarjan

int dfncnt , dfn[maxn + 5] , low[maxn + 5];
bool in_stack[maxn + 5];
int tp , st[maxn + 5];
int sc;
vector<int> scc[maxn + 5];
void tarjan(int u){
    dfn[u] = low[u] = ++dfncnt;
    st[++tp] = u , in_stack[u] = true;
    for(int v : e[u]){
        if(dfn[v] == 0){
            tarjan(v);
            low[u] = min(low[u] , low[v]);
        }
        else if(in_stack[v]){
            low[u] = min(low[u] , dfn[v]);
        }
    }
    if(low[u] != dfn[u]) return;
    sc++;
    while(true){
        int v = st[tp];
        in_stack[v] = false;
        scc[sc].push_back(v);
        tp--;
        if(v == u) break;
    }
}
fo(u , 1 , n){
    if(dfn[u] == 0) tarjan(u);
}

网络流

最大流

struct Dinic{
    private:
    const long long inf = 1000000000000000000;
    int n , s , t;
    struct node{
        int v , rev;
        long long w;
    };
    vector<node> e[maxn + 5];
    int k[maxn + 5] , dep[maxn + 5];
    queue<int> q;
    bool bfs(){
        fo(i , 1 , n) dep[i] = -1;
        dep[s] = 1;
        while(q.size()) q.pop();
        q.push(s);
        while(q.size()){
            int u = q.front();
            q.pop();
            for(node x : e[u]){
                int v = x.v;
                long long w = x.w;
                if(dep[v] != -1 or w == 0) continue;
                dep[v] = dep[u] + 1;
                if(v == t) return true;
                q.push(v);
            }
        }
        return false;
    }
    long long dfs(int u , long long flow){
        if(u == t) return flow;
        long long used = 0;
        for(int &i = k[u] ; i < e[u].size() ; i++){
            int v = e[u][i].v;
            int rev = e[u][i].rev;
            long long& w = e[u][i].w;
            if(dep[v] <= dep[u] or w == 0) continue;
            long long flowv = dfs(v , min(flow - used , w));
            if(flowv == 0) continue;
            w -= flowv;
            e[v][rev].w += flowv;
            used += flowv;
            if(used == flow) break;
        }
        return used;
    }
    public:
    void init(int inputn , int inputs , int inputt){
        n = inputn , s = inputs , t = inputt;
        fo(i , 1 , n) e[i].clear();
    }
    void add(int u , int v , long long w){
        int sizu = e[u].size();
        int sizv = e[v].size();
        e[u].push_back({v , sizv , w});
        e[v].push_back({u , sizu , 0});
    }
    long long maxflow(){
        long long ans = 0;
        while(bfs()){
            fo(i , 1 , n) k[i] = 0;
            long long flow = dfs(s , inf);
            while(flow > 0){
                ans += flow;
                flow = dfs(s , inf);
            }
        }
        return ans;
    }
}qwq;

最小费用流

#include<queue>
#include<vector>
const int maxnode = 5000;
const long long inf = 1000000000;
struct Dinic_mincost{
    private:
    int n , s , t;
    struct node{
        int v , rev;
        long long w , cost;
    };
    vector<node> e[maxnode + 5];
    queue<int> q;
    bool vis[maxnode + 5];
    long long dep[maxnode + 5];
    bool spfa(){
        fo(i , 1 , n) dep[i] = inf , vis[i] = false;
        while(q.size()) q.pop();
        dep[s] = 0 , vis[s] = true;
        q.push(s);
        while(q.size()){
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for(node x : e[u]){
                int v = x.v;
                long long w = x.w , cost = x.cost;
                if(w == 0) continue;
                if(dep[v] <= dep[u] + cost) continue;
                dep[v] = dep[u] + cost;
                if(vis[v] == true) continue;
                vis[v] = true;
                q.push(v);
            }
        }
        return (dep[t] < inf);
    }
    int k[maxnode + 5];
    long long dfs(int u , long long flow , long long& mincost){
        if(u == t) return flow;
        long long used = 0;
        vis[u] = 1;
        for(int& i = k[u] ; i < e[u].size() ; i++){
            int v = e[u][i].v , rev = e[u][i].rev;
            long long& w = e[u][i].w , cost = e[u][i].cost;
            if(w == 0 or dep[v] != dep[u] + cost or vis[v]) continue;
            long long flowv = dfs(v , min(flow - used , w) , mincost);
            if(flowv == 0) continue;
            w -= flowv;
            e[v][rev].w += flowv;
            mincost += flowv * cost;
            used += flowv;
            if(used == flow) break;
        }
        vis[u] = 0;
        return used;
    }
    public:
    void init(int inputn , int inputs , int inputt){
        n = inputn , s = inputs , t = inputt;
        fo(i , 1 , n) e[i].clear();
    }
    void add(int u , int v , long long w , long long cost){
        int sizu = e[u].size();
        int sizv = e[v].size();
        e[u].push_back({v , sizv , w , cost});
        e[v].push_back({u , sizu , 0 , -cost});
    }
    pair<long long , long long> max_flow(){
        long long maxflow = 0 , mincost = 0;
        while(spfa()){
            fo(i , 1 , n) k[i] = 0;
            long long flow = dfs(s , inf , mincost);
            while(flow != 0){
                maxflow += flow;
                flow = dfs(s , inf , mincost);
            }
        }
        return mp(maxflow , mincost);
    }
}qwq;

数学

组合数学

int fac[maxn + 5] , inv[maxn + 5];
int qpow(int a , int b){
    if(b == 0) return 1;
    int ans = qpow(a , b / 2);
    if(b % 2) return 1ll * ans * ans % mod * a % mod;
    else return 1ll * ans * ans % mod;
}
// 记得一定要调用 init 喵,没调用全部草饲喵
void init(){
    fac[0] = 1;
    fo(i , 1 , maxn) fac[i] = 1ll * fac[i - 1] * i % mod;
    inv[maxn] = qpow(fac[maxn] , mod - 2);
    go(i , maxn - 1 , 0) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
}
int getinv(int a){
    return 1ll * inv[a] * fac[a - 1] % mod;
}
int C(int n , int m){
    return 1ll * fac[n] * inv[n - m] % mod * inv[m] % mod;
}

数论

int gcd(int a , int b){
    if(b == 0) return a;
    return gcd(b , a % b);
}
// 欧拉筛求 mu
int mu[maxn + 5];
bool notprime[maxn + 5];
vector<int> prime;
void seive(){
    mu[1] = 1;
    fo(i , 2 , maxn){
        if(notprime[i] == false){
            mu[i] = -1;
            prime.push_back(i);
        }
        for(int p : prime){
            if(1ll * p * i > maxn) break;
            notprime[p * i] = true;
            if(i % p == 0){
                mu[p * i] = 0;
                break;
            }
            mu[p * i] = -mu[i];
        }
    }
}

其他小trick

创建 \(n\)\(m\) 列的矩阵

vector<vector<int>> dp(n + 5 , vector<int>(m + 5 , 0));

STL 的迭代器

set<node> :: iterator it = s.begin();
// 有一次将 set<node> :: iterator it 写成 set<int> :: iterator it 看了好久
// 当然你也可以放心用 auto
auto it = s.begin();
// 尽管 map set 不是线性的,但你仍然可以
it-- , it++;
// 来找它的前后继

priority_queue 的使用

priority_queue<node> q;
// 首先不要拼错,其次默认为大根堆
// 如果要小根堆
priority_queue<node , vector<node> , greater<node> > q;
// vector 表明实现方式, 即 node 是存在 vector 中的
// greater 与 less 相对, 表明从大到小
// 需要重载 > 号

在字符串后加字符

string s;
s = s + "I love Elaina";  // O(n)
s += "I love Elaina"; // O(1)

随机数

#include<ctime>
#include<random>
mt19937 rd(time(0));
shuffle(a + 1 , a + n + 1 , rd);
// 将 a[1 , n] 随机打乱,rd为提供的随机化函数
posted @ 2026-02-07 09:35  Natho_nA  阅读(33)  评论(0)    收藏  举报