acwing笔记

2023-05-16

文章目录

    • 基础知识
      • 快速排序
      • 归并排序
      • 二分查找
    • 基础数据结构
      • 数组模拟单链表
      • trie字符串统计
      • 并查集
      • 堆模板
    • 搜索和图论
      • 邻接表数组实现
      • dfs
      • bfs
      • kmp
      • 最短路
      • 最小生成树
      • 二分图
    • 数学知识
    • 动态规划dp
      • 背包问题
    • 贪心

基础知识

快速排序


/**
 * @brief: 快速排序: 递归,分治
 * @time cpl: O(nlog n)
 * @space cpl: O(1)
 * @trouble:
 **/
template <typename type>
void quick_sort_helper(type *arr, int start, int end);

template <typename type>
int partition(type *arr, int start, int end);

template <typename type>
void quick_sort(type *arr, int size)
{
    quick_sort_helper(arr, 0, size-1);
}

template <typename type>
void quick_sort_helper(type *arr, int start, int end)
{
    if (start > end) return;

    int pivotIndex = partition(arr, start, end);
    quick_sort_helper(arr, start, pivotIndex - 1);
    quick_sort_helper(arr, pivotIndex + 1, end);
}

template <typename type>
int partition(type *arr, int start, int end)
{
    int l = start, r = end, pivot = arr[start];
    type tmp;

    while (true)
    {
        while (arr[l] <= pivot)
        {
            l ++;
            if(l == r) {break;}
        }

        while (arr[r] > pivot)
        {
            r--;
            if(l == r) {break;}
        }

        if(l >= r)
        {
            break;
        }
        else
        {
            tmp = arr[l];
            arr[l] = arr[r];
            arr[r] = tmp;
        }
    }

    tmp = arr[start];
    arr[start] = arr[r];
    arr[r] = tmp;
    return r;
}

归并排序


/**
 * @brief: 归并排序: 递归,分治
 * @time cpl: O(nlog n)
 * @space cpl: O(n)
 * @trouble:
 **/
template <typename type>
void merge_helper(type *arr, type *tmp, int start, int mid, int end);

template <typename type>
void merge_sort_helper(type *arr, type *tmp, int start, int end);

//容易出错传入end = size
template <typename type>
void merging_sort(type *arr, int size)
{
    type tmp[size];
    merge_sort_helper(arr, tmp, 0, size-1);
}

template <typename type>
void merge_two_array(type *arr, type *tmp, int start, int mid, int end)
{
    int i = start, j = mid + 1;
    int m = mid, n = end;
    int k = 0;
    while(i<=m && j<=n)
    {
        if (arr[i] <= arr[j])
            tmp[k++] = arr[i++];
        else
            tmp[k++] = arr[j++];
    }

    while (i<=m)    tmp[k++] = arr[i++];
    while (j<=n)    tmp[k++] = arr[j++];
    for(i = 0; i<k; i++)    arr[start+i] = tmp[i];
}

template <typename type>
void merge_sort_helper(type *arr, type *tmp, int start, int end)
{
    if(end <= start) return;
    int mid = start + (end -start)/2;
    merge_sort_helper(arr, tmp, start, mid);
    merge_sort_helper(arr, tmp, mid+1, end);
    merge_two_array(arr, tmp, start, mid, end);
}

二分查找

template<typename type>
int bip_find(const type num[], const type& target, int start, int end){
    int l = start, r = end;
    while(l <= r){
        int mid = l + (r - l) / 2;
        if(num[mid] > target){
            r = mid - 1;
        }else if(num[mid] < target){
            l = mid + 1;
        }else{
            return mid;
        }
    }
    return -1;
}

基础数据结构

数组模拟单链表

// head存储链表头,idx表示当前用到了哪个节点, e[]存储节点的值,ne[]存储节点的next指针
const int N = 10010;

int head = -1, idx = 0, e[N], ne[N];

// 头部插入节点
void insert(int a){
    e[idx] = a; ne[idx] = head; head = idx; idx++;
}

// 删除头节点
void remove(){
    head = ne[head];
}

// 遍历
for(int i = head; i != -1; i = ne[i]){
    cout << e[i] << " ";
}

trie字符串统计

const int N = 10010; // > 最长字符串长度
int son[N][26], cnt[N], idx;

void insert(char *str){
    int p = 0;
    for (int i = 0; str[i]; i ++ ){
        int u = str[i] - 'a';
        if (!son[p][u]) son[p][u] = ++ idx;
        p = son[p][u];
    }
    cnt[p]++;
}

// 查询字符串出现的次数
int query(char *str)
{
    int p = 0;
    for (int i = 0; str[i]; i ++ )
    {
        int u = str[i] - 'a';
        if (!son[p][u]) return 0;
        p = son[p][u];
    }
    return cnt[p];
}

并查集

int p[N]; //存储每个点的祖宗节点

// 返回x的祖宗节点
int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

// 初始化,假定节点编号是1~n
for (int i = 1; i <= n; i ++ ) p[i] = i;

// 合并a和b所在的两个集合:
p[find(a)] = find(b);

堆模板

// h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1
// ph[k]存储第k个插入的点在堆中的位置
// hp[k]存储堆中下标是k的点是第几个插入的
int h[N], ph[N], hp[N], size;

// 交换两个点,及其映射关系
void heap_swap(int a, int b)
{
    swap(ph[hp[a]],ph[hp[b]]);
    swap(hp[a], hp[b]);
    swap(h[a], h[b]);
}

void down(int u)
{
    int t = u;
    if (u * 2 <= size && h[u * 2] < h[t]) t = u * 2;
    if (u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
    if (u != t)
    {
        heap_swap(u, t);
        down(t);
    }
}

void up(int u)
{
    while (u / 2 && h[u] < h[u / 2])
    {
        heap_swap(u, u / 2);
        u >>= 1;
    }
}

// O(n)建堆
for (int i = n / 2; i; i -- ) down(i);

// 添加: 尾插, 尾上升。
// 删除堆顶:首尾互换,尾删除,首下沉

搜索和图论

邻接表数组实现

// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], idx, e[N], ne[N];

idx = 0; memset(h, -1, sizeof h);

void add(int a, int b){z
    e[idx] = b, ne[idx] = h[a], h[a] = idx, idx++;
}

dfs

void dfs(int u){
    used[u] = true;
    for(int i=h[u]; i != -1; i = ne[i]){
        int j = e[i];
        if(!used[j]) dfs([j]);
    }
}

bfs

queue<int> q;
used[1] = true; q.push(1);

while(!q.empty()){
    int t = q.front(); q.pop();
    for(int i = h[t]; i != -1; i = ne[i]){
        int j = e[i];
        if(!used[j]){
            used[j] = true;
            q.push(j);
        }
    }
}

kmp

// s[]是长文本,p[]是模式串,n是s的长度,m是p的长度
求模式串的Next数组:
for (int i = 2, j = 0; i <= m; i ++ )
{
    while (j && p[i] != p[j + 1]) j = ne[j];
    if (p[i] == p[j + 1]) j ++ ;
    ne[i] = j;
}

// 匹配
for (int i = 1, j = 0; i <= n; i ++ )
{
    while (j && s[i] != p[j + 1]) j = ne[j];
    if (s[i] == p[j + 1]) j ++ ;
    if (j == m)
    {
        j = ne[j];
        // 匹配成功后的逻辑
    }
}

最短路

  • 最短路
    • 单源最短路

      • 边权全正

        • 稠密图: 朴素Dijkstra(n^2), 每次从【未求出最短路径的点】中去除距离起点距离最小的点,并用这个点去更新【未求出最短路径的点】的距离。
        • 稀疏图: 堆优化Dijkstra(mlogn),【未求出最短路径的点】用小根堆存储
      • 存在负边:

        • Bellman-Ford(nm):对所有的边进行n-1轮松弛操作
        • SPFA(m - nm): 由于松弛操作中只有上一节点有变化,当前节点才需要更新,所以用队列记录有变化的节点而无需遍历所有节点。
          • 求最短路径:
          • 判负环:增加一个修改次数计数数组,如果某个节点计数 > n,则说明存在负环。
    • 多源最短路

      • Floyd

最小生成树

  • Prim:循环n-1次,每次从 【未并入生成树中的点集】中找出一条距离 【已并入生成树中的点集】的最小边

    • 稠密图(n^2):朴素版,
    • 稀疏图(mlogn):堆优化版, 麻烦,基本不用,不如直接用Kruskal.
  • Kruskal(mlogm)

二分图

  • 染色法(m+n):对每个点进行一次dfs并交替染色,直至有矛盾出现
  • 匈牙利算法( < mn):

数学知识

质数, 约数, 欧拉函数,

动态规划dp

背包问题

背包体积V, n个物体,体积v_i, 价值w_i, 求背包最大价值

  1. 01背包: 每个物品仅能取一次
  2. 完全背包:每个物品可取无限次
  3. 多重背包:每个物品可用限制次数不一样
  4. 分组背包:物品分组,每一组中只能取一个物品

贪心

  1. 区间选点: 求最少点,落遍所有区间 | 右端点排序,取右端点,每次新的区间左端点在上一区间右端点右侧(即上一点够不着当前区间),则计数++
  2. 最大不相交区间数量:求最大区间数,彼此不相交 | 和上一问题完全一致
  3. 区间分组:求最少分组数,组内区间彼此不相交 | 左端点排序,借助小根堆,新区间每次查询能否放在已有的组里面,不能则成为新的组
  4. 区间覆盖:求最少区间数,覆盖指定区间 | 左端点排序, 每次取最长区间
  5. 合并果子:类似合并石子(相邻合并),但可任取两两合并 | 每次取最小的两堆合并
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

acwing笔记 的相关文章

  • acwing蓝桥杯 - 数学知识【上】

    目录 质数 试除法判定质数 分解质因数 筛质数 约数 试除法求约数 约数个数 约数之和 最大公约数 质数 试除法判定质数 这个算法广为人知 xff0c 这里就不证明了 xff0c 解释一下 i lt 61 n 的写法 1 不推荐写成i lt
  • 蓝桥杯AcWing 题目题解 - 二分与前缀和、差分

    目录 AcWing 789 数的范围 整数二分 AcWing 790 数的三次方根 实数二分 AcWing 730 机器人跳跃问题 二分应用 AcWing 1227 分巧克力 AcWing 795 前缀和 AcWing 796 子矩阵的和
  • acwing蓝桥杯 - 数学知识【下】

    目录 欧拉函数 快速幂 求组合数 I 博弈论 Nim游戏 欧拉函数 在数论 xff0c 对正整数n xff0c 欧拉函数是小于n的正整数中与n互质的数的数目 xff0c 记作 n 1 61 1 1 分解质因子 xff0c 求出质因子p 2
  • AcWing 756. 蛇形矩阵

    题目 输入两个整数n和m 输出一个n行m列的矩阵 将数字 1 到 n m 按照回字蛇形填充至矩阵中 具体矩阵形式可参考样例 输入格式 输入共一行 包含两个整数n和m 输出格式 输出满足要求的矩阵 矩阵占n行 每行包含m个空格隔开的整数 数据
  • AcWing 849. Dijkstra求最短路 I &&II

    给定一个 n 个点 m 条边的有向图 图中可能存在重边和自环 所有边权均为正值 请你求出 1 号点到 n 号点的最短距离 如果无法从 1 号点走到 n 号点 则输出 1 输入格式 第一行包含整数 nn 和 mm 接下来 mm 行每行包含三个
  • 【AcWing】827. 双链表

    双链表 实现一个双链表 双链表初始为空 支持5种操作 在最左侧插入一个数 在最右侧插入一个数 将第 k个插入的数删除 在 第 k个插入的数左侧插入一个数 在第 k个插入的数右侧插入一个数 现在要对该链表进行 M次操作 进行完所有操作后 从左
  • AcWing 425. 明明的随机数

    题目 明明想在学校中请一些同学一起做一项问卷调查 为了实验的客观性 他先用计算机生成了N个1到1000之间的随机整数 对于其中重复的数字 只保留一个 把其余相同的数去掉 不同的数对应着不同的学生的学号 然后再把这些数从小到大排序 按照排好的
  • AcWing.102. 最佳牛围栏(二分&&双指针&&前缀和)

    输入样例 10 6 6 4 2 10 3 8 5 9 4 1 输出样例 6500 解析 1 由题意可知答案位于 1 2000以内 所以可以二分这个区间 2 对于每个mid 我们要看是否存在一个区间 这个区间的平均值大于mid 如果存在返回t
  • AcWing 376. 机器任务(最小点覆盖&&匈牙利算法)

    输入样例 5 5 10 0 1 1 1 1 2 2 1 3 3 1 4 4 2 1 5 2 2 6 2 3 7 2 4 8 3 3 9 4 3 0 输出样例 3 解析 二分图最小点覆盖 最大匹配数 所以跑一边匈牙利算法即可 include
  • AcWing 104. 货仓选址

    题目 在一条数轴上有 N 家商店 它们的坐标分别为 A1 AN 现在需要在数轴上建立一家货仓 每天清晨 从货仓到每家商店都要运送一车商品 为了提高效率 求把货仓建在何处 可以使得货仓到每家商店的距离之和最小 输入格式 第一行输入整数N 第二
  • AcWing 3375. 成绩排序

    题目 题目链接3375 成绩排序 思路 思路要求稳定排序或者特判的快排 写法一 写两个sort中的比较函数的参数cmp 写法二 直接在结构体中进行比较 写法三 归并排序 代码1 include
  • AcWing110. 防晒

    输入样例 3 2 3 10 2 5 1 5 6 2 4 1 输出样例 2 解析 按照右区间排序 优先满足小的 include
  • AcWing 372. 棋盘覆盖(二分图&&匈牙利算法)

    输入样例 8 0 输出样例 32 解析 n为100 状压肯定爆 将每个骨牌看成二分图的一个匹配 即查找二分图的一个最大匹配 匈牙利算法 include
  • AcWing 1381. 阶乘

    题目 N 的阶乘 记作 N 是指从 1 到 N 包括 1 和 N 的所有整数的乘积 阶乘运算的结果往往都非常的大 现在 给定数字 N 请你求出 N 的最右边的非零数字是多少 例如 5 1 2 3 4 5 120 所以 5 的最右边的非零数字
  • AcWing 99. 激光炸弹(二维前缀和)

    输入样例 2 1 0 0 1 1 1 1 输出样例 1 解析 二维前缀和 枚举每个正方形区间的最大值即可 本题只能开一个5000的二维数组 两个会MLE 代码 include
  • acwing 第63场周赛【2022.08.06】

    acwing第63场周赛 2022 08 06 一 4503 数对数量 1 题目描述 2 思路分析 3 代码实现 二 4504 字符串消除 1 题目描述 2 思路分析 3 代码实现 三 4505 最大子集 1 题目描述 2 思路分析 3 代
  • 243. 一个简单的整数问题2(树状数组)

    输入样例 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4 输出样例 4 55 9 15 解析 一般树状数组都是单点修改 区间查询或者单点查询 区间修改 这道题都是区间操作
  • 考研算法辅导课总结-持续更新中

    这考研算法辅导课总结 建议根据大标题和题号来刷题 排序和进位制 3375 成绩排序 3376 成绩排序2 3373 进制转换 3374 进制转换2 链表和日期问题 66 两个链表的第一个公共节点 3756 筛选链表 3757 重排链表 36
  • Acwing 826. 单链表 (用数组模拟单链表)

    实现一个单链表 链表初始为空 支持三种操作 1 向链表头插入一个数 2 删除第k个插入的数后面的数 3 在第k个插入的数后插入一个数 现在要对该链表进行M次操作 进行完所有操作后 从头到尾输出整个链表 注意 题目中第k个插入的数并不是指当前
  • 蓝桥杯 - 负载均衡

    输入样例 2 6 5 5 1 1 5 3 2 2 2 6 3 1 2 3 4 1 6 1 5 1 3 3 6 1 3 4 输出样例 2 1 1 1 1 0 解析 优先队列 排序规则为任务结束的时间 在新任务的时候 弹出已经结束的任务 并且恢

随机推荐