自用板子合集

最近开始学新算法了;

篛嵇死了,啥也不会,只能背板子了;

感谢@Nihachu的博客

 

快读

int型

复制代码
inline int read()
{
    int xr = 0,flag = 1;
    char lcr;
    while(lcr = getchar(),lcr < '0' or lcr > '9'){
        if(lcr == '-'){
            flag = -1;
        } 
    }
    while(lcr >= '0' and lcr <= '9'){
        xr = (xr << 3) + (xr << 1) + (lcr ^ 48);
        lcr = getchar();
    }
    return xr * flag;
}
复制代码

 

快写

 

复制代码
void write(int x)
{
    if(x<0)
        putchar('-'),x=-x;
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
    return;
}
复制代码

 

二叉树相关

1、深度优先DFS:

前序遍历(根,左子树,右子树)

void dfs(int x){
    printf("%d\n",x);
    if(ls[x]) dfs(ls[x]);
    if(rs[x]) dfs(rs[x]);
}

中序遍历(左子树,根,右子树)

void dfs(int x){
    if(ls[x]) dfs(ls[x]);
    printf("%d\n",x);
    if(rs[x]) dfs(rs[x]);
}

后续遍历(左子树,右子树,根)

void dfs(int x){
    if(ls[x]) dfs(ls[x]);
    if(rs[x]) dfs(rs[x]);
    printf("%d\n",x);
}

2、广度优先BFS:

层次遍历(从上到下,从左到右依次输出同一层的节点):

复制代码
void bfs(int x){
    q[++top] = x;
    for(int i = 1; i <= top; i ++){
        int now = q[i];
        printf("%d\n",now);
        if(ls[now]) q[++top] = ls[now];
        if(rs[now]) q[++top] = rs[now];
    }
}
复制代码

动规

1、01背包(已降维)

for(int i = 1; i <= n; i ++){
    for(int j = m; i >= w[i]; j --){
        dp[j] = max(dp[j],dp[j - w[i]] + v[i]);
    }
}

2、完全背包

for(int i = 1; i <= n; i ++){
    for(int j = w[i]; i <= m; j ++){
        dp[j] = max(dp[j],dp[j - w[i]] + v[i]);
    }
}

3、背包计数

(若要求恰好为m,则dp[0]初始化为1,其他均为0);

for(int i = 1; i <= n; i ++){
    for(int j = m; i >= w[i]; j --){
        dp[j] += dp[j - w[i]];
    }
}

4、二进制拆分(用于多重背包)

for(int i = 1; i <= n1; i ++){
    scanf("%d %d %d",&a, &b, &c);
    for(int k = 1; k <= c; k <<= 1){
        v[++u] = k * a; w[u] = k * b;
        c -= k;
    }
    if(c) v[++u] = a * c,w[u] = b * c;
}

并查集

1、查询 + 路径压缩

int find(int x){
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}

2、合并x,y所属集合

void marge(int x, int y){
    int u = find(x), v = find(y);
    if(u == v) return;
    fa[u] = v;
}

3、合并x, y 所属集合(按秩合并)

void marge(int x, int y){
    int u = find(x), v = find(y);
    if(u == v) return;
    if(rk[u] > rk[v]) swap(u,v); // 把深度小的合并到深度大的上面; 
    fa[u] = v;
    rk[v] += rk[u] == rk[v]; //如果同级,则合并后深度加一,否则不变; 
}

单调队列

复制代码
//n为数据个数,m为窗口长度; 
for(int i = 1; i <= n; i ++){
    if(q[head] <= i - m) head ++;
    while(head <= tail && a[q[tail]] < a[i]) tail --;
    q[++tail] = i;
    ans[i] = a[q[head]];
}
for(int i = m ; i <= n ; i ++){
    //对每个窗口中已选出的数据进行处理 ; 
}
复制代码

图论

1、链式前向星

void add(int x, int y){
    to[++cnt] = y;
    nxt[cnt] = head[x];
    head[x] = cnt;
}

 2.spfa

复制代码
void spfa()
{
    memset(dis,0x3f,sizeof dis);
    dis[s] = 0;
    z[top = 1] = s;
    for(int j = 1;j <= top;++ j){
        int now = z[j];
        vis[now] = 0;
        for(int i = head[now];i;i = nxt[i]){
            if(dis[to[i]] > dis[now] + w[i]){
                dis[to[i]] = dis[now] + w[i];
                if(!vis[to[i]]){
                    vis[to[i]] = 1;
                    z[++ top] = to[i];
                }
            }
        }
    }
}
复制代码

 线段树

1.初始建树

复制代码
inline void build(int l,int r,int id)
{
    if(l == r){
        sum[id] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(l,mid,id * 2);
    build(mid + 1,r,id * 2 + 1);
    sum[id] = sum[id * 2] + sum[id * 2 + 1];
}
复制代码

 2.单点查询

复制代码
inline int query(int l,int r,int id,int x)
{
    if(l == r){
        return sum[id];
    }
    int mid = (l + r) >> 1;
    if(x <= mid){
        query(l,mid,id * 2,x);
    }
    else{
        query(mid + 1,r,id * 2 + 1,x);
    }
}
复制代码

3.单点修改

复制代码
inline void change(int l,int r,int x,int v,int k)
{
    if(l == r){
        sum[k] += v;
        return;
    }
    int mid = (l + r) >> 1;
    int res = 0;
    if(x <= mid){
        change(l,mid,x,v,k * 2);
    }
    else{
        change(mid + 1,r,x,v,k * 2 + 1);
    }
    sum[k] = sum[k * 2] + sum[k * 2 + 1];
}
复制代码

4.区间查询

复制代码
nt query(int l,int r,int x,int y,int k)//区间[x,y]
{
    if(x <= l and y >= r){
        return sum[k];
    }
    int mid = (l + r) >> 1;
    int res = 0;
    if(x <= mid){
        res += query(l,mid,x,y,k * 2);
    }
    if(y >= mid){
        res += query(mid + 1,r,x,y,k * 2 + 1);
    }
    return res;
}
复制代码

5.带懒标记的区间修改查询

复制代码
//lazytag
inline void add_(int l,int r,int k,int v)
{
    add[k] += v;
    sum[k] += v * (r - l + 1);
}

inline void pushdown(int l,int r,int mid,int k)
{
    if(!add[k]){
        return;
    }
    add_(l,mid,add[k],k * 2);
    add_(mid + 1,r,add[k],k * 2 + 1);
    add[k] = 0;
}

inline int query(int l,int r,int x,int y,int k)
{
    if(x <= l and y >= r){
        return sum[k];
    }
    int mid = (l + r) >> 1;
    int res = 0;
    pushdown(l,r,mid,k);
    if(x <= mid){
        res += query(l,mid,x,y,k * 2);
    }
    if(y > mid){
        res += query(mid + 1,r,x,y,k * 2 + 1);
    }
    return res;
}

void change(int l,int r,int x,int y,int k,int v)
{
    if(x <= l and y >= r){
        return sum[k];
    }
    int mid = (r + l) >> 1;
    int res = 0;
    pushdown(l,r,mid,k);
    if(x <= mid){
        change(l,mid,x,y,k * 2,v);
    }
    if(y > mid){
        change(mid + 1,r,x,y,k * 2 + 1,v);
    }
    sum[k] = sum[k * 2] + sum[k * 2 + 1];
}
复制代码

 字符串

1.kmp

复制代码
//n为a的长度,m为b的长度
inline void jiannxt()
{
    nxt[1] = 0;
    for(int i = 1,j = 0;i < m;++ i){
        while(j and b[j + 1] != b[i + 1]){
            j = nxt[j];
        }
        if(b[j + 1] == b[i + 1]){
            ++ j;
        }
        nxt[i + 1] = j;
    }
}

inline int kmp()
{
    int ans = 0;
    for(int i = 0;i < n;++ i){
        while(j and b[j + 1] != a[i + 1]){
            j = nxt[j];
        }
        if(b[j + 1] == a[i + 1]){
            ++ j;
        }
        if(j == m){
            ++ ans;
            j = nxt[j];
        }
    }
    return ans;
}
复制代码

 

posted @   Qwehhh  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示