代码相关

upd on 26.3.4 代码风格由

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

改为

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

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

字符串哈希

const int maxl = 100005;
const int mod1 = 1000000007;
const int base1 = 131;
const int mod2 = 998244353;
const int base2 = 233;
int powbase1[maxl] , powbase2[maxl];
void init(){
	powbase1[0] = 1;
	fo(i , 1 , maxl - 5)
		powbase1[i] = 1ll * powbase1[i - 1] * base1 % mod1;
	powbase2[0] = 1;
	fo(i , 1 , maxl - 5)
		powbase2[i] = 1ll * powbase2[i - 1] * base2 % mod2;
}
struct mystring{
	string s;
	int len;
	pair<int , int> hsh[maxl];
	void read(){
		cin >> s;
		len = s.size();
		s = " " + s;
		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;
		}
	}
	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];
	}
};

树状数组

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;

可持久化线段数

不想写喵,以后做题时写了再补上

线段树其他

动态开点、权值线段树的合并,支持单点修改,线段树二分以查询 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;

平衡树

#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;
    }
};

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));
    }
};

点分树

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);
    }
}

重链剖分

附加求 LCA 的代码

int siz[maxn + 5] , fa[maxn + 5] , dep[maxn + 5] , son[maxn + 5] , top[maxn + 5] , idx , dfn[maxn + 5];
void dfs1(int u , int f){
    siz[u] = 1 , fa[u] = f , dep[u] = dep[f] + 1;
    for(int v : e[u]){
        if(v == f) continue;
        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(int v : e[u]){
        if(v == fa[u]) continue;
        if(v == son[u]) continue;
        dfs2(v , v);
    }
}
void 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;
}

数论相关

现在只写了求逆元

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;
}

其他小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 Eleina";  // O(n)
s += "I love Eleina"; // O(1)

随机数

#include<ctime>
#include<random>
mt19937 rd(time(0));
posted @ 2026-02-07 09:35  Samhu07  阅读(16)  评论(0)    收藏  举报